W przypadku, gdy masz wiele dyrektyw na jednym elemencie DOM i gdy kolejność, w jakiej są stosowane, ma znaczenie, możesz użyć priority
właściwości do zamówienia ich aplikacji. Wyższe liczby są uruchamiane jako pierwsze. Domyślny priorytet to 0, jeśli go nie określisz.
EDYCJA : po dyskusji, oto kompletne działające rozwiązanie. Kluczem było usunąć atrybut : element.removeAttr("common-things");
, a także element.removeAttr("data-common-things");
(w przypadku użytkowników określić data-common-things
w 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);
}
};
}
};
});
Działający plunker jest dostępny pod adresem : http://plnkr.co/edit/Q13bUt?p=preview
Lub:
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);
}
};
});
PRÓBNY
Wyjaśnienie, dlaczego musimy ustawić terminal: true
i priority: 1000
(dużą liczbę):
Gdy DOM jest gotowy, kątowy prowadzi DOM w celu zidentyfikowania wszystkich zarejestrowanych dyrektyw i kompilowania dyrektyw jeden po drugim w oparciu o to, priority
czy te dyrektywy dotyczą tego samego elementu . Możemy ustawić priorytet nasz zwyczaj dyrektywy do dużej liczby, aby zapewnić, że zostanie skompilowany pierwszy i terminal: true
, pozostałe dyrektywy zostaną pominięte po tej dyrektywy jest skompilowany.
Kiedy nasza niestandardowa dyrektywa zostanie skompilowana, zmodyfikuje element, dodając dyrektywy i usuwając się, i używa usługi $ compile do skompilowania wszystkich dyrektyw (w tym tych, które zostały pominięte) .
Jeśli nie ustawimy terminal:true
i priority: 1000
, istnieje szansa, że niektóre dyrektywy zostaną skompilowane przed naszą niestandardową dyrektywą. A kiedy nasza niestandardowa dyrektywa używa $ compile do skompilowania elementu => ponownie skompiluj już skompilowane dyrektywy. Spowoduje to nieprzewidziane zachowanie, szczególnie jeśli dyrektywy skompilowane przed naszą niestandardową dyrektywą już przekształciły DOM.
Aby uzyskać więcej informacji o priorytecie i terminalu, sprawdź Jak zrozumieć „terminal” dyrektywy?
Przykładem dyrektywy, która również modyfikuje szablon jest ng-repeat
(priorytet = 1000), kiedy ng-repeat
jest kompilowany, ng-repeat
wykonaj kopię elementu szablonu przed zastosowaniem innych dyrektyw .
Dzięki komentarzowi @ Izhaki tutaj znajduje się odniesienie do ngRepeat
kodu źródłowego: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js
RangeError: Maximum call stack size exceeded
kompilacja trwa wiecznie.