Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

AngularJS 1.5 directive link execution order #13884

Open
alangria opened this issue Jan 29, 2016 · 5 comments
Open

AngularJS 1.5 directive link execution order #13884

alangria opened this issue Jan 29, 2016 · 5 comments

Comments

@alangria
Copy link

Hello,

Does AngularJS 1.5 change the directive link execution order?

Suppose that you have

  • ParentDirective
    • ChildDirective

In 1.4.8 the execution would be

  • ParentDirective: pre-link
    • ChildDirective: controller
    • ChildDirective: pre-link
    • ChildDirective: post-link
  • ParentDirective: post-link

in 1.5.0 the execution of ParentDirective's postlink was done before ChildDirective's postlink

@Narretz
Copy link
Contributor

Narretz commented Jan 29, 2016

Doesn't look like it: http://plnkr.co/edit/QKlsLNyr0RrECqeSDDRc?p=preview

It's possible that because of lazy transclusion you're seeing something diffeent. We'll need a demo of that though.

@mragentman
Copy link

I think this issue may be related to something I ran into with a project that I am working on. I had this same question about the link execution order when moving from Angular 1.4.8 to 1.5.0-rc.2. I want to post a few Plunkers to demonstrate what is happening but I want to also express that this does not appear to be a bug with Angular. This ends up falling into an unspecified behavioral case rather than being a bug between 1.4.8 and 1.5.0. Thanks to @dcherman for going through the Angular code with me to determine if it was related to a change he made in 1.5.0-beta.1.

This first Plunker shows that the link order is correctly bottom up in Angular 1.4.8. The child directive is linked before the wrapping parent directive. Everything is as expected with this example.
Angular 1.4.8 - http://plnkr.co/edit/8y9lexxGhlEelF0vEVyx?p=preview
Angular 1.5.0-rc.2 - http://plnkr.co/edit/hQbXfCP0lb6wqAG2DumJ?p=preview

Next, I will introduce an async template via the templateUrl attribute. Here, with the same DOM structure, we can see that the bottom up linking cannot be guaranteed. The Angular documentation points this out that parent and sibling directives will link before the children due to the async nature of templateUrl.
Angular 1.4.8 - http://plnkr.co/edit/zatqXlx2R3DUXgoLu8oV?p=preview
Angular 1.5.0-rc.2 - http://plnkr.co/edit/iEU1E8KzaaZCXaQebqGg?p=preview

If we add an ng-repeat around the parent -> child DOM, we can see that the bottom up linking returns in Angular 1.4.8. In speaking with @dcherman, this has to do with the way transcluded directives eagerly fetch template urls and replace them with a derived synchronous one. This process allows the child template to be available when the child directive is compiled rather than following the typical async template pattern.
Angular 1.4.8 - http://plnkr.co/edit/O3ePJDoRQ4NUGRwaityo?p=preview
Angular 1.5.0-rc.2 - http://plnkr.co/edit/E5vsgucBLWzLn3xE3gRX?p=preview

In this last example, we see that the behavior in Angular 1.5.0-rc.2 looks to have changed when directives are wrapped in an ng-repeat but this is due to the way transcluded directives process async templates. Now that 1.5.0 lazily compiles transcluded content, it can cause directives with templateUrl to link in a different order than bottom-up since that eager compilation was altered.

Lastly, the fix for my application, since I am using Gulp and ngtemplates to preload all of my template files into the $templateCache, was to change the template in the directive from being async to synchronous. This was done by switching templateUrl with template and calling $templateCache.get() on the template url. Here is the last Plunker I will post to demonstrate this:
http://plnkr.co/edit/7fWmxSqhMV2VYwwWWGPk?p=preview

Hopefully everyone made it to the end of my lengthy description. @alangria - I am not sure if you were experiencing this with regards to a transcluded directive like ng-repeat but I hope this information helps you track down the issue in your application.

@benweet
Copy link

benweet commented Feb 28, 2016

+1, thanks @mragentman for your post.

@michi88
Copy link

michi88 commented Mar 20, 2016

There should be something about this in the release notes as this breaks animations on a trivial case (when not to be fixed).

Better yet, do not allow for lazy compilation when templateUrl is not cached yet. Easy to say, I know. ;)

https://plnkr.co/edit/okAirW34LQ8uCYzR7Ijf?p=preview

see: #14074

@michi88
Copy link

michi88 commented Mar 20, 2016

After reading this commit I think we should be able to opt-out of this behaviour 652b83e

mbenford added a commit to mbenford/ngTagsInput that referenced this issue May 10, 2016
Reverse the order that an event is triggered so the autocomplete directive
can work correctly with Angular 1.5, since the order that child directives
are compiled has been changed in that version of the framework, due to lazy
transclusion (see angular/angular.js#13884 and
angular/angular.js@652b83e).

Closes #638
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants