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:
- Faça o fork do projeto e adapte meus requisitos em cima dele.
- 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 tabset
diretiva do AngularUI Bootstrap .
Ele fornece um active
atributo, 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 tabDirective
e estendendo o link
método via compile
(o retorno de compile
é sempre Link
).
Link nos permite adicionar ao scope
, portanto, dentro do meu Link
mé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 link
mé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!