Nei casi in cui hai più direttive su un singolo elemento DOM e in cui l'ordine in cui sono applicati è importante, puoi utilizzare la priority
proprietà per ordinare la loro applicazione. I numeri più alti vengono eseguiti per primi. La priorità predefinita è 0 se non ne specifichi uno.
EDIT : dopo la discussione, ecco la soluzione di lavoro completa. La chiave era rimuovere l'attributo :, element.removeAttr("common-things");
e anche element.removeAttr("data-common-things");
(nel caso in cui gli utenti specifichino data-common-things
nell'html)
angular.module('app')
.directive('commonThings', function ($compile) {
return {
restrict: 'A',
replace: false,
terminal: true, //this setting is important, see explanation below
priority: 1000, //this setting is important, see explanation below
compile: function compile(element, attrs) {
element.attr('tooltip', '{{dt()}}');
element.attr('tooltip-placement', 'bottom');
element.removeAttr("common-things"); //remove the attribute to avoid indefinite loop
element.removeAttr("data-common-things"); //also remove the same attribute with data- prefix in case users specify data-common-things in the html
return {
pre: function preLink(scope, iElement, iAttrs, controller) { },
post: function postLink(scope, iElement, iAttrs, controller) {
$compile(iElement)(scope);
}
};
}
};
});
Il plunker di lavoro è disponibile all'indirizzo: http://plnkr.co/edit/Q13bUt?p=preview
O:
angular.module('app')
.directive('commonThings', function ($compile) {
return {
restrict: 'A',
replace: false,
terminal: true,
priority: 1000,
link: function link(scope,element, attrs) {
element.attr('tooltip', '{{dt()}}');
element.attr('tooltip-placement', 'bottom');
element.removeAttr("common-things"); //remove the attribute to avoid indefinite loop
element.removeAttr("data-common-things"); //also remove the same attribute with data- prefix in case users specify data-common-things in the html
$compile(element)(scope);
}
};
});
DEMO
Spiegazione del motivo per cui dobbiamo impostare terminal: true
e priority: 1000
(un numero elevato):
Quando il DOM è pronto, Angular accompagna il DOM per identificare tutte le direttive registrate e compilare le direttive una per una in base al fatto priority
che queste direttive siano sullo stesso elemento . Impostiamo la priorità della nostra direttiva personalizzata su un numero elevato per garantire che venga compilata per prima e terminal: true
, con le altre direttive, verranno ignorate dopo che questa direttiva è stata compilata.
Quando viene compilata la nostra direttiva personalizzata, modificherà l'elemento aggiungendo direttive e rimuovendo se stesso e utilizzando il servizio $ compile per compilare tutte le direttive (comprese quelle che sono state ignorate) .
Se non impostiamo terminal:true
e priority: 1000
, è possibile che alcune direttive vengano compilate prima della nostra direttiva personalizzata. E quando la nostra direttiva personalizzata usa $ compile per compilare l'elemento => compila di nuovo le direttive già compilate. Ciò causerà un comportamento imprevedibile soprattutto se le direttive compilate prima della nostra direttiva personalizzata hanno già trasformato il DOM.
Per maggiori informazioni su priorità e terminale, controlla Come capire il "terminale" della direttiva?
Un esempio di direttiva che modifica anche il modello è ng-repeat
(priorità = 1000), quando ng-repeat
viene compilato, ng-repeat
crea copie dell'elemento modello prima che vengano applicate altre direttive .
Grazie al commento di @ Izhaki, ecco il riferimento al ngRepeat
codice sorgente: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js
RangeError: Maximum call stack size exceeded
mentre continua a compilare per sempre.