Ответ 1
аргументация
postLink()
выполняется в обратном порядке, что означает, что postLink()
директива postLink()
будет вызываться перед родительским (т.е. сначала первой). По какой-то причине это поведение по умолчанию (link()
самом деле относится к postLink()
). К счастью, у нас также есть preLink()
, который работает наоборот - мы можем использовать это в свою пользу.
Чтобы проиллюстрировать это - следующий фрагмент кода:
app.directive('parent', function($log) {
return {
restrict: 'E',
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) {
$log.info('parent pre');
},
post: function postLink(scope, iElement, iAttrs, controller) {
$log.info('parent post');
}
}
}
};
});
app.directive('child', function($log) {
return {
restrict: 'E',
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) {
$log.info('child pre');
},
post: function postLink(scope, iElement, iAttrs, controller) {
$log.info('child post');
}
}
}
};
});
... выводит следующее:
> parent pre
> child pre
> child post
> parent post
См. live on plunker.
Решение
Если мы хотим, чтобы родительская директивная логика выполнялась перед дочерним preLink()
, мы будем явно использовать preLink()
:
function SortableWidgetsDirective() {
return {
restrict: 'A',
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) {
iElement.find(".widget header").append($("<div class='widget-controls'></div>"));
iElement.sortable({});
},
post: angular.noop
}
}
};
}
function CloneableWidgetDirective() {
return {
restrict: 'A',
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) {
iElement.find("header .widget-controls").append($("<div class='clone-handle'></div>"));
},
post: angular.noop
}
}
};
}
Рекомендации
-
$compile
в документах AngularJS.
Пост скриптум
-
Вы, кстати, правы -
priority
предназначен для использования с директивами, которые имеют один и тот же элемент. -
angular.noop
- это пустой метод, который ничего не возвращает. Если вы все еще хотите использовать функцииpostLink()
, просто поместите объявление функции, как обычно, например:post: function postLink(scope, iElement, iAttrs, controller) { ... }
-
Будьте использовать
templateUrl
, так как "поскольку загрузка шаблона асинхронна, компиляция/привязка приостановлена до тех пор, пока шаблон не будет загружен" [source]. В результате порядок исполнения будет нарушен. Вы можете исправить это, включив в него шаблон, встроенный в свойствоtemplate
.