Estendendo a diretiva angular

Eu gostaria de fazer uma pequena modificação em uma diretiva de terceiros (especificamente Angular UI Bootstrap ). Eu simplesmente quero adicionar ao escopo da diretiva pane :

 angular.module('ui.bootstrap.tabs', []) .controller('TabsController', ['$scope', '$element', function($scope, $element) { // various methods }]) .directive('tabs', function() { return { // etc... }; }) .directive('pane', ['$parse', function($parse) { return { require: '^tabs', restrict: 'EA', transclude: true, scope:{ heading:'@', disabled:'@' // <- ADDED SCOPE PROPERTY HERE }, link: function(scope, element, attrs, tabsCtrl) { // link function }, templateUrl: 'template/tabs/pane.html', replace: true }; }]); 

Mas também quero manter o Angular-Bootstrap atualizado com o Bower. Assim que eu executar a bower update , sobrescrevo minhas alterações.

Então, como eu faço para estender esta diretiva separadamente deste componente de arquibancada?

Provavelmente, a maneira mais simples de resolver isso é criar uma diretiva em seu aplicativo com o mesmo nome da diretiva de terceiros. Ambas as diretivas serão executadas e você poderá especificar sua ordem de execução usando a propriedade priority (a prioridade mais alta será executada primeiro).

As duas diretivas compartilharão o escopo e você poderá acessar e modificar o escopo da diretiva de terceiros por meio do método de link sua diretiva.

Opção 2: Você também pode acessar o escopo de uma diretiva de terceiros simplesmente colocando sua própria diretiva nomeada arbitrariamente no mesmo elemento com ela (assumindo que nenhuma diretiva use escopo isolar). Todas as diretivas de escopo não isoladas em um elemento compartilharão o escopo.

Leitura adicional: https://github.com/angular/angular.js/wiki/Dev-Guide%3A-Understanding-Directives

Nota: Minha resposta anterior foi para modificar um serviço de terceiros, não uma diretiva.

TL; DR – gimme tha demo!


Botão de demonstração


Use o decorator() $provide para, bem, decorar a diretiva do terceiro.

No nosso caso, podemos estender o escopo da diretiva da seguinte forma:

 app.config(function($provide) { $provide.decorator('paneDirective', function($delegate) { var directive = $delegate[0]; angular.extend(directive.scope, { disabled:'@' }); return $delegate; }); }); 

Primeiro, pedimos para decorar a diretiva do pane passando seu nome, concatenado com a Directive como o primeiro argumento, e depois recuperamos o nome do parâmetro de retorno de chamada (que é uma matriz de diretivas correspondentes a esse nome).

Uma vez obtido, podemos obter seu object de escopo e estendê-lo conforme necessário. Observe que tudo isso precisa ser feito no bloco de config .

Algumas notas

  • Foi sugerido simplesmente adicionar uma diretiva com o mesmo nome e, em seguida, definir seu nível de prioridade. Além de ser anti-social (o que não é nem uma palavra , eu sei…), apresenta questões, por exemplo, e se o nível de prioridade da diretiva de terceiros mudar?

  • JeetendraChauhan afirmou (eu não testei embora) que esta solução não funcionará na versão 1.13.

Embora esta não seja a resposta direta à sua pergunta, você pode querer saber que a versão mais recente (em mestra) do http://angular-ui.github.io/bootstrap/ adicionou suporte para desabilitar as guias. Esse recurso foi adicionado por meio de: https://github.com/angular-ui/bootstrap/commit/2b78dd16abd7e09846fa484331b5c35ece6619a2

Outra solução em que você cria uma nova diretiva que a estende sem modificar a diretiva original

A solução é semelhante à solução decoradora:

Crie uma nova diretiva e injete como dependência a diretiva que você deseja estender

 app.directive('extendedPane', function (paneDirective) { // to inject a directive as a service append "Directive" to the directive name // you will receive an array of directive configurations that match this // directive (usually only one) ordered by priority var configExtension = { scope: { disabled: '@' } } return angular.merge({}, paneDirective[0], configExtension) }); 

Dessa forma, você pode usar a diretiva original e a versão estendida no mesmo aplicativo

Aqui está outra solução para um cenário diferente de extensão de ligações para uma diretiva que possui a propriedade bindToController .

Nota: esta não é uma alternativa para outras soluções que foram oferecidas aqui. Ele resolve apenas um caso específico (não abordado em outras respostas) em que a diretiva original foi configurada com bindToController .