10

I'm fairly new to Javascript programming and I have only touched upon AngularJS. In order to evaluate it I decided to write a simple note application. The model is really simple, a list of notes where each note has a label, a text and a list of tags. However I ran into problem passing data between isolated scopes of nested directives.

I have three directives, notes, note and tagger (defining new elements with the same names). Each of them using an isolated scope.

The notes directive uses ng-repeat to "render" each one of its notes with the note element.

The note directive uses the tagger element to "render" the list of tags.

The note directive defines scope: { getNote: "&", ... } in order to pass a note instance from the list of notes to the note controller/directive. The getNote(index) function is called in the link function of the note directive. This works fine!

The tagger directive defines scope: { getTags: "&", ... } in order to pass a list of tags for a given note to the tagger controller/directive. The getTags function is called in the link function of the tagger directive. This does not work!

As I understand it, the problem is that the link functions of the directives are called in an inconsistent order. Debugging the application shows that the link functions are called in the following order:

  1. link function in the notes directive (adding the getNote function to the notes scope)

  2. link function in the tagger directive of the first note (calling getTags in the parent note scope) function

  3. link function in the first note directive (adding the getTags to the scope) (calling getNote in the parent notes scope)

  4. link function in the tagger directive of the second note (calling getTags in the parent note scope) function

  5. link function in the second note directive (adding the getTags to the scope) (calling getNote in the parent notes scope)

This will not work since in #2 the scope of the first note has not yet an getTags function.

A simplistic example can be found in Plunker.

Hence, my question boils down to: What determines the order in which link functions are called in nested directives.

(I solved to the problem using $watch on getTags in the tagger directive...)

regards

1

2 Answers 2

18

Quoting Josh D. Miller who had kindly responded to a similar question I had :

" Just a couple of technical notes. Assume that you have this markup:

<div directive1>
  <div directive2>
    <!-- ... -->
  </div>
</div>

Now AngularJS will create the directives by running directive functions in a certain order:

directive1: compile

directive2: compile

directive1: controller

directive1: pre-link

directive2: controller

directive2: pre-link

directive2: post-link

directive1: post-link

By default a straight "link" function is a post-link, so your outer directive1's link function will not run until after the inner directive2's link function has ran. That's why we say that it's only safe to do DOM manipulation in the post-link. "

Sign up to request clarification or add additional context in comments.

2 Comments

Hi @Tahir thanks for answering. Perhaps I'm stupid but, as seen in my plunker, I have: <notes><note><tagger></tagger></note></notes> but link function calling order is <notes>, <tagger>, <note> ... while <tagger>, <note>, <notes> would be expected according to your answer... Sorry if I'm being stupid :-)
I would tend to think that it is a mix of things because not only ng-repeat executes with priority=1000 (and you have nested ng-repeat statements). But you don't seem to use the transclude option so I am not too sure about the compilation order of your embedded directives.
0

On a single element the order of the linking functions is determined by the order of the Compile Functions which in turn is ordered according to the priority property of the directive definition object.

Source : http://docs.angularjs.org/guide/directive

On multiple elements with transclusion : the inner directives are evaluated before outer directives. Reason: Nature of transclusion.

On multiple elements with siblings : Executed in order top to bottom. Reason: Parsing logic of $compile.

1 Comment

Hi @basarat,thanks for taking some time answering! However I fail to apply your answer on my question. I do not have multiple directives on the same element. I do not use transclusion. My note elements are of course siblings but I am not sure understand what you mean. Perhaps it is obvious but I still do not understand the calling order of the link functions in my Plunker example. Reagrds

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.