Dans les cas où vous avez plusieurs directives sur un seul élément DOM et où l'ordre dans lequel elles sont appliquées, vous pouvez utiliser la priority
propriété pour ordonner leur application. Les nombres plus élevés s'exécutent en premier. La priorité par défaut est 0 si vous n'en spécifiez pas.
EDIT : après la discussion, voici la solution de travail complète. La clé était de supprimer l'attribut :, element.removeAttr("common-things");
et aussi element.removeAttr("data-common-things");
(au cas où les utilisateurs le spécifieraient data-common-things
dans le 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);
}
};
}
};
});
Plunker de travail est disponible à: http://plnkr.co/edit/Q13bUt?p=preview
Ou:
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
Explication pourquoi nous devons définir terminal: true
et priority: 1000
(un nombre élevé):
Lorsque le DOM est prêt, angular parcourt le DOM pour identifier toutes les directives enregistrées et compiler les directives une par une en fonction de priority
si ces directives se trouvent sur le même élément . Nous avons défini la priorité de notre directive personnalisée sur un nombre élevé pour nous assurer qu'elle sera compilée en premier et avec terminal: true
, les autres directives seront ignorées après la compilation de cette directive.
Lorsque notre directive personnalisée est compilée, elle modifie l'élément en ajoutant et en supprimant elle-même et en utilisant le service $ compile pour compiler toutes les directives (y compris celles qui ont été ignorées) .
Si nous ne définissons pas terminal:true
et priority: 1000
, il est possible que certaines directives soient compilées avant notre directive personnalisée. Et lorsque notre directive personnalisée utilise $ compile pour compiler l'élément => recompiler à nouveau les directives déjà compilées. Cela entraînera un comportement imprévisible, surtout si les directives compilées avant notre directive personnalisée ont déjà transformé le DOM.
Pour plus d'informations sur la priorité et le terminal, consultez Comment comprendre le `terminal` de la directive?
Un exemple de directive qui modifie également le modèle est ng-repeat
(priorité = 1000), quand il ng-repeat
est compilé, ng-repeat
faites des copies de l'élément de modèle avant que d'autres directives ne soient appliquées .
Merci au commentaire de @ Izhaki, voici la référence au ngRepeat
code source: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js
RangeError: Maximum call stack size exceeded
fur et à mesure de sa compilation.