Confused about Angularjs, enclosed and isolation areas and bindings

I'm struggling to understand the scale of models and their bindings for directives that have limited scope.

I understand that limiting the scope of a directive means that it is a controller. $ scope and directive.scope are no longer the same. However, I am confused by how placing models in a directive template or in html affects data binding. I feel that I am missing something very fundamental and move on. I need to understand this.

Take the following code (here is the script: http://jsfiddle.net/2ams6/ )

Javascript

var app = angular.module('app',[]); app.controller('Ctrl',function($scope){ }); app.directive('testel', function(){ return { restrict: 'E', scope: { title: '@' }, transclude: true, template: '<div ng-transclude>'+ '<h3>Template title: {{title}}</h3>' + '<h3>Template data.title:{{data.title}}</h3>' + '</div>' } }); 

HTML

 <div ng-app='app'> <div ng-controller="Ctrl"> <input ng-model="data.title"> <testel title="{{data.title}}"> <h3>Transclude title:{{title}}</span></h3> <h3>Transclude data.title:{{data.title}}</h3> </testel> </div> </div> 

Only the model updates {{title}} inside the template and {{data.title}} in the transition. Why not {{title}} in the transition and {{data.title}} in the template?

Moving input to the so-called transition (fiddle here: http://jsfiddle.net/eV8q8/1/ ):

 <div ng-controller="Ctrl"> <testel title="{{data.title}}"> <input ng-model="data.title"> <h3>Transclude title: <span style="color:red">{{title}}</span></h3> <h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3> </testel> </div> 

now means that only transclude {{data:title}} updated. Why not create a template {{title}} or {{data.title}} and translate {{title}} ?

And finally, moving the input inside the template like this (fiddle here: http://jsfiddle.net/4ngmf/2/ ):

 template: '<div ng-transclude>' + '<input ng-model="data.title" />' + '<h3>Template title: {{title}}</h3>' + '<h3>Template data.title: {{data.title}}</h3>' + '</div>' 

Now means that only the {{data.title}} template is updated. Again, why not the other 3 bindings?

I hope there is something obvious looking in my face and I miss him. If you let me get this, I will buy you a beer or give you some points or something else. Thank you very much.

+54
angularjs angularjs-scope angularjs-directive
May 20 '13 at 15:34
source share
3 answers

Your scripts create three areas:

  • area associated with Ctrl controller due to ng-controller
  • transcluded scope directive, due to transclude: true
  • the directive isolates the scope, due to scope: { ... }

In fiddle1, before entering anything into the text box, we have the following:

enter image description here

Area 003 is the area associated with the controller. Since we have not yet entered text in the text field, there is no data property. In selection area 004, we see that the title property was created, but it is empty. It is empty because the parent area does not yet have the data.title property.

After entering my title in the text box, we now have:

enter image description here

Controller area 003 now has a new property on the data object (therefore it is painted yellow), whose title property is now set to my title . Since the scope property of the title isolation is a unidirectional binding to the interpolated value of data.title , it also gets the value my title (the color is yellow because it has changed).

The specified prototype area is inherited from the controller scope, so inside the enclosed HTML angular can follow the prototype chain and find $scope.data.title in the parent area (but $scope.title does not exist there).

The selection area has access only to its own properties, therefore only the title property.

In fiddle2, before entering, we have the same picture as in the violin.

After entering my title :

enter image description here

Notice where the new data.title property data.title - in a closed area. The selection area is still looking for data.title in the controller area, but it does not exist this time, so its title property value remains empty.

In fiddle3, before entering, we have the same image as in fiddle1.

After entering my title :

enter image description here

Notice where the new data.title property data.title - in the isolation area. None of the other areas have access to the isolation area, so the string my title will no longer be displayed.




Update for angular v1.2:

With the change of eed299a, angular now clears the transition point before overlapping, so the parts of Template title: ... and Template data.title: ... t, unless you change the template so that ng-transclude is on its own, eg:

 '<h3>Template title: <span style="color:red">{{title}}</span></h3>' + '<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>' + '<div ng-transclude></div>' 

In the update below for angular v1.3, this template change was made.




Update for angular v1.3 +:

Since angular v1.3, the transcluded scope is now a child of the directive's scope, and not a child of the controller scope. So, in fiddle1, before we type anything:

enter image description here

Images in this update are drawn using the Peri $ scope tool, so the images are slightly different. @ indicates that we have an isolation scope property that uses the @ syntax, and a pink background means that the tool could not find a reference to the ancestor for matching (which is true because we haven't entered anything into the text box yet).

After entering my title in the text box, we now have:

enter image description here

Isolating properties that use the @ binding will always show the result of the interpolated string in the selection area after the @ symbol. Peri $ scope was also able to find this exact string value in the ancestral region, so it also shows a link to this property.

In script 2, before entering, we have the same picture as in the violin.

After entering my title :

enter image description here

Notice where the new data.title property data.title - in a closed area. The selection area is still looking for data.title in the controller area, but it does not exist this time, so its title property value remains empty.

In fiddle3, before entering, we have the same image as in fiddle1.

After entering my title :

enter image description here

Notice where the new data.title property data.title - in the isolation area. Despite the fact that the transcoded access area has access to the isolation area via the $parent relation, it will not look there for title or data.title - it will only look in the controller area (i.e., it will follow the prototype inheritance ), and the control area does not have these properties.

+113
May 23, '13 at 3:28
source share

After reading all the answers provided, including Mark fair schematics, this is my understanding of the scope and its inheritance on my question. I would appreciate comments on where this chart falls so I can update it accordingly. Hope this just gives a different idea of ​​what Mark introduced:

Scope inheritance

+22
May 24 '13 at 12:52
source share

Well asked, by the way! I hope my answer will be equally eloquent.

The answer should be related to how the transmitted elements get their scope.

To summarize, you have two areas:

  • A management scope that has $scope.data.title . (Implicitly added by your input element)
  • The scope of the directive, which has $scope.title .

Changing the $scope.data.title controller also changes the $scope.title directive.

You also have two HTML sections, broadcast and template. What happens is that the translated HTML is in the controller area, and the HTML template is in the scope of the directive. Thus, the translated HTML does not know anything about title , and the template area does not know anything about data.title

Actually, this is exactly what Transclusion was intended for - so that the children of the directive retain their parent area, in this case the control area. By design, transcoded elements do not know that they are in the directive, and therefore do not have access to the scope of the directive.

Directive templates, on the other hand, will only have access to the scope of the directive.

I modified my code a bit to make the names more understandable (however, functionality)

http://jsfiddle.net/yWWVs/2/

+8
May 20 '13 at 16:14
source share



All Articles