Estenda claramente as diretivas AngularJS de terceiros

Muitas vezes, uma diretiva escrita por alguma outra mente brilhante me leva quase onde preciso ir, mas não exatamente.

No passado, eu lidava com isso de duas maneiras:

  1. Faça o fork do projeto e adapte meus requisitos em cima dele.
  2. Escreva uma solução do zero para resolver meu problema.

Embora essas opções sejam boas , elas dificilmente são flexíveis, e a segunda delas pode poluir desnecessariamente a comunidade e desperdiçar um tempo valioso.

Entrar decoradores

O Angular nos dá a capacidade de realmente modificar as diretivas existentes ou próprias configurações do aplicativo, o problema é que não parece ser muito bem documentado …

Exemplo:

Recentemente, eu queria ter a capacidade de definir dinamicamente uma guia ativa para a tabsetdiretiva do AngularUI Bootstrap .

Ele fornece um activeatributo, mas não é gravável, fazendo com que ele não seja definido por algo como, digamos,ui-router

Minha configuração

angular.module('myApp')
.config(function($provide) {

/**
* Hijacking the AngularUI Tabs directive

* We need a way to set an active tab based on current router state

* By default this is only supported when using tabs via an `ngRepeat` loop.

*

* @example

<tab isactive="vm.test(isTrue)">tab contents</tab>

*/

$provide
.decorator('tabDirective', function($delegate) {
var directive, link;
directive
= $delegate[0];
link
= directive.link;
directive
.compile = function() {
return function Link(scope, element, attrs, ctrls) {
scope
.active = scope.$parent.$eval(attrs.isactive);
return link.apply(this, arguments);
};
};
return $delegate;
});

}));

Basicamente, o que está acontecendo aqui é que estou pegando a diretiva antes que meu aplicativo carregue, puxando tabDirectivee estendendo o linkmétodo via compile(o retorno de compileé sempre Link).

Link nos permite adicionar ao scope, portanto, dentro do meu Linkmétodo personalizado , estou avaliando um novo atributo que apliquei às minhas guias, chamado isactive.

scope.$parent.$eval irá realmente disparar o método com o escopo existente.

Eu concluo tudo retornando o linkmétodo original com minhas atualizações, simplesmente aplicando meu link e todos os argumentos a ele:return link.apply(this, arguments);

Tudo feito!

Usando este mesmo estilo, você pode essencialmente sobrescrever / estender qualquer aspecto de uma diretiva (ou fábrica, provedor, serviço). Eu também usei isso para alterar os modelos de diretivas para o meu próprio design.

directive.templateUrl = 'app/path/to/directive/template.html';

Feliz Hacking!