В тех случаях, когда у вас есть несколько директив для одного элемента DOM, и когда порядок, в котором они применяются, имеет значение, вы можете использовать это priority
свойство для заказа их приложения. Более высокие числа запускаются первыми. Приоритет по умолчанию - 0, если вы его не указали.
РЕДАКТИРОВАТЬ : после обсуждения, вот полное рабочее решение. Ключ должен был удалить атрибут :, 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 готов, angular обходит DOM, чтобы идентифицировать все зарегистрированные директивы и компилировать директивы одну за другой, основываясь на priority
том, находятся ли эти директивы в одном и том же элементе . Мы устанавливаем приоритет нашей пользовательской директивы на большое число, чтобы гарантировать, что она будет скомпилирована первой, а terminal: true
другие директивы будут пропущены после компиляции этой директивы.
Когда наша пользовательская директива компилируется, она изменяет элемент, добавляя директивы и удаляя себя, и использует $ compile service для компиляции всех директив (включая те, которые были пропущены) .
Если мы не установим terminal:true
и priority: 1000
, есть вероятность, что некоторые директивы скомпилированы перед нашей пользовательской директивой. И когда наша пользовательская директива использует $ compile для компиляции element => compile снова уже скомпилированные директивы. Это приведет к непредсказуемому поведению, особенно если директивы, скомпилированные до нашей пользовательской директивы, уже преобразовали DOM.
Для получения дополнительной информации о приоритете и терминале, посмотрите Как понять `терминал` директивы?
Примером директивы, которая также изменяет шаблон, является ng-repeat
(приоритет = 1000), когда ng-repeat
он скомпилирован, ng-repeat
создайте копии элемента шаблона перед применением других директив .
Благодаря комментарию @ Izhaki, вот ссылка на ngRepeat
исходный код: https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js
RangeError: Maximum call stack size exceeded
как он вечно компилируется.