pomerantsev / angular-training

An empty repo for creating tasks as issues
0 stars 0 forks source link

Why are two ng-view Directives registered? #2

Open al-the-x opened 10 years ago

al-the-x commented 10 years ago

This gets complicated quickly, so probably worthy of another half-hour. The two (there are actually three in that file) are collaborating to produce the effect we see as ng-view. As API consumers, we only use the ng-view Directive; the others are by-products of our usage.

al-the-x commented 10 years ago

Originally taken from #1

al-the-x commented 10 years ago

Starting from https://github.com/angular/angular.js/blob/master/src/ngRoute/directive/ngView.js

al-the-x commented 10 years ago

From the Angular JS docs re $compile

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 compile functions get called. Priority is defined as a number. Directives with greater numerical priority are compiled 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.

terminal

If set to true then the current priority will be the last set of directives which will execute (any directives at the current priority will still execute as the order of execution on same priority is undefined).

Key points:
As an exercise:
pomerantsev commented 10 years ago

The picture is this: if we add two directives to the same element, then the execution sequence is the following:

The next step, I guess, is trying to remember what the sequence is in a complex DOM structure where directives with different priorities are assigned to different elements. Would you suggest any example that would best illustrate such a sequence?

al-the-x commented 10 years ago

Well, generally avoid introducing this level of complexity into your own applications and Directive chains. It's useful for Composition: breaking logic into smaller, collaborating pieces on the same element. Constrast that to traditional OOP Inheritance: children inheriting functionality from parents. On Jun 16, 2014 3:10 AM, "pomerantsev" notifications@github.com wrote:

The picture is this: if we add two directives to the same element, then the execution sequence is the following:

  • both compile functions (highest to lowest priority);
  • both controllers (highest to lowest);
  • both pre-link functions (highest to lowest);
  • both post-link functions (lowest to highest). Setting terminal on the high-priority directive makes the other one never compile.

The next step, I guess, is trying to remember what the sequence is in a complex DOM structure where directives with different priorities are assigned to different elements. Would you suggest any example that would best illustrate such a sequence?

— Reply to this email directly or view it on GitHub https://github.com/pomerantsev/angular-training/issues/2#issuecomment-46147132 .

pomerantsev commented 10 years ago

This is what I do and don't understand about the ng-view directives. No need to answer here - but something to talk about on Friday.

ngViewFactory has transclude: ‘element’. Which means: transclude the whole element including any directives defined at lower priority. (according to https://docs.angularjs.org/api/ng/service/$compile). What does it actually mean? currentScope - the scope in which the ngView directive is compiled. What is scope equal to in the link function? What’s the point in having scope, currentScope and newScope? If a template is defined on the given route, then a new scope is created (as a child of the directive scope, with scope.$new()). Then we’re creating a clone - what does this mean? What does the transclude function return? Why are we overriding the scope in $transclude (what would the scope be if we didn’t pass one)? currentElement probably acts as the previous ng-view element (since it’s stored in the closure, we get access to it next time we run the update() function (when $routeChangeSuccess is fired)). What is the value of clone inside the $transclude’s callback? Is it the same element that $transclude returns? Does $transclude return a jqLite-wrapped element? Why are we assigning something to current.scope? What’s happening in cleanupLastView()? What are previousElement, currentElement and currentScope at the moment when this function gets called? Why does the seconds directive get called during the $transclude call? Comments in the code: “We need this directive so that the element content is already filled when the link function of another directive on the same element as ngView is called.” - what does this mean? In this second directive, the ng-view element gets filled with the template, and then this template gets compiled in the ng-view’s scope (what is this scope at this moment? how does it relate to the new scope created in the first directive?). Why do we set $ngControllerController data attributes on ng-view and all its children?

al-the-x commented 10 years ago
pomerantsev commented 10 years ago

Trying to register a directive after the app has been bootstrapped doesn't work for me: http://plnkr.co/edit/lPIrcfqZOyOHmhjlaEyc The problem is, it is never being registered. I guess I'm doing something wrong here.

pomerantsev commented 10 years ago

Been reading the source code and the docs. A lot of things there that I don't understand. Here are some sentences that I'd like to discuss in depth.

API reference: https://docs.angularjs.org/api/ng/service/$compile

Compiler guide: https://docs.angularjs.org/guide/compiler

Suggested homework for me (let’s discuss):

pomerantsev commented 10 years ago

Hey @al-the-x - reminding you that you were going to give me some task to work on for me to better understand what we were talking about yesterday. Thanks!

pomerantsev commented 10 years ago

Oh - and have a good 4th!

al-the-x commented 10 years ago

Thanks, Pavel. Travel safely this weekend, and I'll write down your homework this evening. Thanks for the reminder! On Jul 4, 2014 11:58 AM, "pomerantsev" notifications@github.com wrote:

Oh - and have a good 4th!

— Reply to this email directly or view it on GitHub https://github.com/pomerantsev/angular-training/issues/2#issuecomment-48058197 .

al-the-x commented 10 years ago

From http://plnkr.co/edit/gqBxcmGIslhcikEAnnsv

With priority: -400:

function arguments file:line
compile2 [JQLite[1], Attributes, false] app.js:53
compile1 [JQLite[1], Attributes, function] app.js:18
controller1 [] app.js:15
prelink1 [$$childScopeClass, JQLite[1], Attributes, Constructor, function] app.js:22
transclude1pre [JQLite[1], $$childScopeClass] app.js:25
controller2 [] app.js:50
prelink2 [$$childScopeClass, JQLite[1], Attributes, Constructor, undefined] app.js:57
postlink2 [$$childScopeClass, JQLite[1], Attributes, Constructor, undefined] app.js:64
postlink1 [$$childScopeClass, JQLite[1], Attributes, Constructor, function] app.js:29
transclude1post [JQLite[1], $$childScopeClass] app.js:32
controller2 [] app.js:50
prelink2 [$$childScopeClass, JQLite[1], Attributes, Constructor, undefined] app.js:57
postlink2 [$$childScopeClass, JQLite[1], Attributes, Constructor, undefined] app.js:64
pomerantsev commented 10 years ago

compile2 compile1 controller2 controller1 prelink2 transclude2pre prelink1 transclude1pre postlink1 transclude1post postlink2 transclude2post

pomerantsev commented 10 years ago

compile2 [JQLite[1], Attributes, false] app.js:53 compile1 [JQLite[1], Attributes, function] app.js:18 controller2 [] app.js:50 controller1 [] app.js:15 prelink2 [$$childScopeClass, JQLite[1], Attributes, Constructor, function] app.js:57 transclude2pre [JQLite[1], $$childScopeClass] app.js:60 prelink1 [$$childScopeClass, JQLite[1], Attributes, Constructor, function] app.js:22 transclude1pre [JQLite[1], $$childScopeClass] app.js:25 postlink1 [$$childScopeClass, JQLite[1], Attributes, Constructor, function] app.js:29 transclude1post [JQLite[1], $$childScopeClass] app.js:32 postlink2 [$$childScopeClass, JQLite[1], Attributes, Constructor, function] app.js:64 transclude2post [JQLite[1], $$childScopeClass]

al-the-x commented 10 years ago
pomerantsev commented 10 years ago

@al-the-x - does this look good overall? https://github.com/pomerantsev/angular-training/blob/master/03-manual-stack-trace/stack-trace-01.md

al-the-x commented 10 years ago

Good start, yes. You might consider annotating the function calls vs the function definitions, e.g.

And so on. Any time you add another function definition to the call stack, indent. Document the params and return values of each function first, then document the functions called.

There's no need to follow these guidelines rigidly. If a simple description of a function seems sufficient, omit the detailed stack trace. Good work. Keep it up...!

pomerantsev commented 10 years ago

Thanks! Distinguishing calls, definitions and params makes perfect sense.