У випадках, коли у вас є кілька директив щодо одного елемента DOM, і де має значення порядок їх застосування, ви можете скористатися priority
властивістю, щоб замовити їх застосування. Вищі числа запускаються першими. Пріоритет за замовчуванням - 0, якщо ви не вказали його.
EDIT : після обговорення ось повне робоче рішення. Ключем було видалення атрибута :, element.removeAttr("common-things");
а також element.removeAttr("data-common-things");
(у випадку, якщо користувачі вказують data-common-things
у 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);
}
};
}
};
});
Робочий плункер доступний за посиланням: http://plnkr.co/edit/Q13bUt?p=preview
Або:
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
Пояснення, чому нам потрібно встановити terminal: true
і priority: 1000
(велике число):
Коли DOM готовий, кутовий прогулянка DOM для виявлення всіх зареєстрованих директив і складання директив по черзі на основі, priority
якщо ці директиви знаходяться на одному елементі . Ми встановлюємо пріоритет нашої спеціальної директиви на велику кількість, щоб переконатися, що вона буде скомпільована першою, а разом з цим terminal: true
, інші директиви будуть пропущені після компіляції цієї директиви.
Коли наша спеціальна директива буде скомпільована, вона буде змінювати елемент, додаючи директиви та видаляючи себе, і використовує службу $ compile для компіляції всіх директив (включаючи ті, що були пропущені) .
Якщо ми не встановимо terminal:true
і priority: 1000
, є ймовірність, що деякі директиви будуть складені раніше нашою спеціальною директивою. І коли наша спеціальна директива використовує $ compile для компіляції елемента => знову компілювати вже складені директиви. Це спричинить непередбачувану поведінку, особливо якщо директиви, складені до нашої спеціальної директиви, вже перетворили DOM.
Для отримання додаткової інформації про пріоритет та термінал, дізнайтеся, як зрозуміти `термінал` директиви?
Прикладом директиви, яка також змінює шаблон, є ng-repeat
(пріоритет = 1000), коли ng-repeat
компілюється, ng-repeat
зробіть копії елемента шаблону до того, як будуть застосовані інші директиви .
Завдяки коментарю @ Іжакі, ось посилання на ngRepeat
вихідний код: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js
RangeError: Maximum call stack size exceeded
як він продовжує збиратись назавжди.