Suppose I have two attribute directive called myFoo
and myBar
. These directives are defined with restrict: 'A'
.
Then I have an element
<div my-foo my-bar></div>
In what order would the piling/linking functions be called? Does my-foo
's pile always be called before my-bar
's pile ?
Suppose I have two attribute directive called myFoo
and myBar
. These directives are defined with restrict: 'A'
.
Then I have an element
<div my-foo my-bar></div>
In what order would the piling/linking functions be called? Does my-foo
's pile always be called before my-bar
's pile ?
2 Answers
Reset to default 6In addition to @valepu's answer here is the description for the priority
property for the DDO (Directive Definition Object):
TL;DR The default priority
is 0
and if you wish to change the order in which elements get piled you'd have to increase the priority
for the element(s).
When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority is used to sort the directives before their pile functions get called. Priority is defined as a number. Directives with greater numerical priority are piled first. Pre-link functions are also run in priority order, but post-link functions are run in reverse order. The order of directives with the same priority is undefined. The default priority is 0.
In your case, if you do not specify the priority
for your directives, my-bar
will be piled first followed by my-foo
. However, notice that the controller gets initialized first, then the pre
followed by the post
link function. Also, the order is important here: Angular piles the directives alternating. The follownig is my console.log
printing which shows the process:
bar controller
foo controller
pre bar
pre foo
post foo
post bar
If you wish to play around, I have set up a Plunker.
Now, if you change the priority
to priority: 1
you will get the following output:
foo controller
bar controller
pre foo
pre bar
post bar
post foo
As you can see, it starts with myFoo
and goes on to myBar
. So myFoo
now has a higher priority.
Update 1
Question:
How do you deal with a sititation, in which two different vendor directives (A and B) depend on each other and the order of execution is important? Is it possible without changing the vedor's settings?
I would suggest to implement a decorator as follows:
app.config(function($provide) {
$provide.decorator('myFooDirective', function($delegate) {
var directive = $delegate[0];
directive.priority = 9;
return $delegate;
});
});
Usually, a decorator intercepts the creation of a service, allowing it to override or modify the behaviour of a service. However, you could also decorate your directive as shown above. In the decorator you could set the priority to your needs to effect the order of execution. As far as I know the priority
property is the only way to control the order in which the directives get applied. When using a decorator you modify / override the priority
property but not directly its settings in case you don't mean the DDO.
The Plunker above is also updated with the decorator implementation.
No, Directives have a field called "priority" which tells angular when they have to be piled. The bigger the priority the earlier they will be piled. So, in your case, the directives will always be piled in the same order (no matter how you write them in the tag) and this order depends on their priority field (default is 0).
from https://docs.angularjs/api/ng/service/$pile
priority
When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority is used to sort the directives before their pile functions get called. Priority is defined as a number. Directives with greater numerical priority are piled first. Pre-link functions are also run in priority order, but post-link functions are run in reverse order. The order of directives with the same priority is undefined. The default priority is 0.
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0, //This is the priority field
/* ....... */
};
return directiveDefinitionObject;
});
This article seems to explain quite well how priority works in different cases: http://www.newyyz./blog/2014/12/15/understanding-priorities-in-angularjs-directive-definition-objects/