Reputation: 270
I have created a directive to understand transclusion and isolated scope. Here is the HTML:
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div>
<input type="text" ng-model="name" />
<input type="number" ng-model="friendCount" />
</div>
<my-friends name="{{name}}">
<p>Hi, I'm {{name}}, and I have {{friendCount}} friends</p>
</my-friends>
</div>
</div>
Directive:
var app = angular.module('myApp', []);
app.controller('MyCtrl', function ($scope) {
$scope.name = "John Doe";
$scope.friendCount = 3;
});
app.directive('myFriends', function () {
return {
restrict: 'E',
replace: true,
template: '<div>' +
' <h3> Isolated Scope: {{name}}</h3>' +
' <div ng-transclude></div>' +
'</div>',
transclude: true,
scope: {
name: '@'
},
link: function (scope, element, attrs) {
scope.name = "Anderson";
}
}
});
Open this fiddle: JsFiddle
I have two questions:
Why does the {{name}} in directive template says "John Doe" instead of "Anderson"? I expected it to be Anderson, since name property is prototypically inherited and as soon as write to it in the link function, it should lose that ancestral connection.
It seems to be transcluding correctly but why does it throw the error Error: [ngTransclude:orphan] in the dev tools console? Could it be the angular version I am using?
Any help is greatly appreciated.
Here is the fiddle: JsFiddle
UPDATE:
The transclusion error was due to loading angular twice by mistake.
When using the @
binding you can overwrite the name
inside directive after the initial digest cycle has completed, for example in an click handler or something. However, it will be overwritten as soon as you change the parent scope's name property.
The issue about @
binding is my misunderstanding of isolated scopes. It is working the way it is supposed to in the example. Isolated scope does not prototypically inherit from parent. And the meaning of @
binding, also referred to as read-only access or one-way binding, is that it will not let you update/write to parent scope.
UPDATED FIDDLE
Upvotes: 2
Views: 888
Reputation: 48982
1) With @
binding, at the digest phase, angular will reevaluate the expression and set the value back to the current value of your controller which will overwrite your value set in the link function.
2) You have 2 versions of angular loaded in the fiddle. The angular loaded the second time walks the DOM again and tries to compile again the already compiled DOM. For more information, take a look at my answer to another question Illegal use of ngTransclude directive in the template
Upvotes: 1
Reputation: 2305
The AngularJS documentation is in such a state of flux that I cannot find the page relevant to the different types of isolated scope bindings so I apologize for any inaccuracies.
scope: {
name: '=' //formerly @
},
IIRC the @
binding takes the value passed in as a string literal. I am not positive why this means the link function assignment doesn't overwrite it, if I could find the section in the docs then I'd link to it.
The =
binding binds to the value of a scope property and updates both the isolate scope and the assigning scope when updated.
<my-friends name="name"> //formerly name="{{name}}"
Using the =
binding means that a scope property needs to be passed instead of a string value.
Again, sorry for any incorrect or vague information. I'll update the answer if I can find the dang documentation.
Upvotes: 1