9
votes

I have a weird situation. If I have an outer directive that contains 2 directives

inner-directive1 - has a template defined.

inner-directive2 - has a templateUrl defined.

The inner-directive1 postLink function is being called before the outer-directive postLink function - as expected.

But, the inner-directive2 poslink function is being called after the outer-directive postLink - NOT as expected.

The calls to the postLink function are : inner-directive1, outer-directive, inner-directive2 and I was expecting : inner-directive1, inner-directive2, outer-directive.

The template for the outer directive is:

<div ng-transclude><div inner1></div><div inner2></div></div>

please look at the JsFiddle

Does anyone know the reason why? And is there a way I can make it work as it is expected ?

JSFiddle - Please look at the console log. Thanks, Ben

2
Can you share the code for the directives?mortalapeman
@mortalapeman just edited the question and added a JsFiddle.Ben Laniado

2 Answers

10
votes

Here's why, from the Angular directive docs(http://docs.angularjs.org/guide/directive):

templateUrl - Same as template but the template is loaded from the specified URL. Because the template loading is asynchronous, the compilation/linking is suspended until the template is loaded.

So that particular directive stops linking until your template is loaded. During that time your other directives jump in and run.

If the timing of you link function is critical, you'll need to include the template directly instead of as a templateUrl. Unless someone can come up with a cool way around this.

1
votes

Not sure of the exact use-case, but I ran into this issue when trying to use element[0].querySelector('#dynamicId');

This would result in "null" in this case since the link function was being executed from input 1 after outer link.

The fix was rather simple, in the outer directive's link function, wrap the code using element.ready():

element.ready(function(){
     var item = element[0].querySelector('#dynamicId');
     item.bind('blur', function(){
         alert('blur')
     });
})

This allows me to find the dynamic element and attach any events even if it's being async loaded from the template url.