Nested - transcluded items - scope clarification?
Asked Answered
D

1

6

I already know how transclusion works ( within first level only I guess) , bUt I have a question about nested transcluded item's scope.

Ok so I have this code :

<body ng-app="docsTabsExample" ng-controller="ctrl">
  <my-tabs>
    <my-pane title="Hello">
      <h4>Hello , The value of "i" is => {{i}}</h4>
   </my-pane>
  </my-tabs>
</body>

Basically I have a controller , <my-tabs> and <my-pane >.

Looking at myTabs directive :

  .directive('myTabs', function()
  {
      return {
          restrict: 'E',
          transclude: true,
          scope:
          {},
          controller: ['$scope', function($scope)
          {
              $scope.i = 2;
          }],
          template: '<div ng-transclude></div>'
      };
  })

I know that the content of the directive will have access to the outer directive's scope

So the yellow part will have access to the outer scope ( which is the main controller scope) :

enter image description here

Here is the code for myPane directive :

  .directive('myPane', function()
  {
      return {
          require: '^myTabs',
          restrict: 'E',
          transclude: true,
          scope:
          {
          },
          controller: function($scope)
          {
              $scope.i = 4; //different value
          },
          template: '<div  ng-transclude></div>'
      };
  })

The program starts with :

.controller('ctrl', function($scope)
{
    $scope.i = 1000;
})

The output of the program is :

Hello , The value of "i" is => 1000

But

According to the documentation : myPane's transcluded data should have access to the outer scope of the directive which is myTabs directive which has the value i=2.

But myPane has an isolated scope so it does NOT inherit the scope from myTabs.

Question

So does it goes one level more higher to the controller's scope in order to get i=1000 ?? (Clarification , I'm not asking how can I make i get another value - I'm asking why/how it has the value of 1000).

I mean how does the hierarchy of scope looks here?

Is it like this?

         controller's scope
                |
       +--------+---------+
       |                  |
  myTabs's             mypanes's
 transcluded           transcluded 
 data's scope          data's scope         

the docs says :

The transclude option changes the way scopes are nested. It makes it so that the contents of a transcluded directive have whatever scope is outside the directive, rather than whatever scope is on the inside. In doing so, it gives the contents access to the outside scope.

But what scope does the outside of myPAne directive has ?

In other words , why/how does i=1000?

FULL PLUNKER

EDIT FROM OP AFTER ANSWER

After installing and configuring PeriScope ( from @MarkRajcok) I can now see it visually :

enter image description here

Detector answered 8/12, 2015 at 17:46 Comment(1)
Both myTab and myPane have transclude: true. myPane is nested within myTab. You're giving myPane the scope of myTab, and then myTab the scope of ctrl, which gives myPane the scope of ctrl.Forcible
V
1

From the docs on $compile

When you call a transclude function it returns a DOM fragment that is pre-bound to a transclusion scope. This scope is special, in that it is a child of the directive's scope (and so gets destroyed when the directive's scope gets destroyed) but it inherits the properties of the scope from which it was taken.

Parent Hierarchy (from $$childTail) is like:

-1 (root)
--2 (ctrl)
---3 mytab
----4 ($$transcluded = true)
------5 mypane
--------6 ($$transcluded = true)

Prototypical Hierarchy is like (screenshot from AngularJS Batarang)-

ng-transclude proto hierarchy

Updated plunker with scope id's printed in console should give you a better idea.

Why these are different, I am not very sure. Someone can throw light on this.

Why the value is 1000. Its because i needs to be provided as a bidirectional attribute = so the child scopes can modify it. I have updated the above plunker, you can see now the value responds to change in pane controller.

More on transcluded scopes -
Confused about Angularjs transcluded and isolate scopes & bindings
https://github.com/angular/angular.js/wiki/Understanding-Scopes

Volatile answered 8/12, 2015 at 18:32 Comment(4)
Why did you add i to the isolated scope? My question did not has it. Also - in your plunker - can you please explain what is "mypane parent 4" ? I know that both mytabs and mypane has isolated(different) scope. but what is mypane parent 4? What is the parent of mypane ?Detector
Transcluded scope is a special scope. In the case above - mypane parent 4 is the transcluded scope. I have updated the post with a link that explains transcluded scope.Volatile
But my question has 2 transcluded items , so why do I see only the 4'th one ?Detector
Right. There is actually a 6th scope as well. I have updated the post. 2 for directives, 2 transcluded, rootscope and ctrl.Volatile

© 2022 - 2024 — McMap. All rights reserved.