Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Directive inner content with isolated and non-isolated scopes

I found quite a strange behaviour of scope:true type for inner content of a directive:

<body ng-init="x=10">
    <mydir>
       {{x}}
    </mydir> 
</body>

so {{x}} is inner content, and directive definition is:

.directive('mydir', function() {
   return {
       scope: {},
       link: function(scope){
           scope.x = 5;
       }
   };
});

When we define scope as isolated (scope:{}), it outputs {{x}} as 10, so uses outer scope. But when we create new scope for the directive(scope:true), it will use it for inner content and output 5. So it uses different scopes for inner content for 2 cases. Could somebody give me a hint/link to souce code/manual for the explanation for this inconsistency?

Here is plnk to play with the code.

UPD: I understand what is JavaScript prototype inheritance. I know the difference between directive scope types. And my aim is not to display 5 instead of 10. The question is about inner template that in both cases should be interpolated with parent scope, which does not have access to properties of child/isolated one.

like image 994
Stepan Suvorov Avatar asked Jan 21 '16 07:01

Stepan Suvorov


3 Answers

In your original code snippet, the {{x}} does not belong to <mydir>. You should define a template to the directive.

// js
.directive('mydir', function() {
   return {
       template: '{{x}}',
       scope: {},
       link: function(scope){
           scope.x = 5;
       }
   };
});

// html
<body ng-init="x=10">
    <mydir></mydir> 
</body>

Here is the preview

like image 154
stanleyxu2005 Avatar answered Nov 11 '22 02:11

stanleyxu2005


A got the answer from angular issues: https://github.com/angular/angular.js/issues/13845#issuecomment-174953398

And here is source code answer: https://github.com/angular/angular.js/blob/eae0a1121ffcc636d760463105dcdc548ea47390/src/ng/compile.js#L2538-L2545

var scopeToChild = scope;
if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
      scopeToChild = isolateScope;
}
childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);

resume: In case of isolated scope type, scope is provided ONLY for directive template, but not for inner content.

like image 3
Stepan Suvorov Avatar answered Nov 11 '22 00:11

Stepan Suvorov


Something not right is going on. If you run your code in Chrome with Batarang turned on, you can see when scope : {} that it is indeed creating a new scope separate from the first, completely disconnected, and setting the variable to 5. But your interpolated string is binding to outer scope. If you set scope : true it is also create a new scope inherited from the outer, and the {{x}} interpolation is binding correctly. I don't think it is scope parameter on the directive that is not working, something with binding is not working.

like image 2
Cleverguy25 Avatar answered Nov 11 '22 01:11

Cleverguy25