Search code examples
angularjsinheritanceangularjs-scopeisolated-scope

In AngularJS, if the child directive cannot access it's immediate parent's scope then would it inherit its nearest, non-isolated ancestor's scope?


I have two examples in favor of the above statement -

1) When using $scope (http://plnkr.co/edit/kFM77mVReS7AUwZsNzCV?p=preview) -

<!DOCTYPE html>
<html>

  <head>
    <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
    <script>
      angular
          .module('myApp', [])
          .directive('directive1', function() {
            return {
              controller: ['$scope', function($scope) {
                $scope.name = 'Directive1';
              }]
            };
          })
          .directive('directive2', function() {
            return {
              controller: ['$scope', function($scope) {
                $scope.name = 'Directive2';
              }],
              scope: {}
            };
          })
          .directive('directive3', function() {
            return {
              template: 'I am {{name}}'
            };
          });
    </script>
  </head>

  <body ng-app='myApp'>
    <directive1>
      <directive2>
        <directive3>
        </directive3>
      </directive2>
    </directive1>
  </body>

</html>

2) When using controllerAs(http://plnkr.co/edit/zmIRa1t87ZIMDS6X5rNo?p=preview)-

 <!DOCTYPE html>
<html>

  <head>
    <script src="//code.angularjs.org/snapshot/angular.min.js"></script>
    <script>
      angular
          .module('myApp', [])
          .directive('directive1', function() {
            return {
              controller: function() {this.name = 'Directive1';},
              controllerAs: 'ctrl1'
            };
          })
          .directive('directive2', function() {
            return {
              controller: function() {this.name = 'Directive2';},
              controllerAs: 'ctrl2',
              transclude: true,
              template: '<ng-transclude></ng-transclude>',
              scope: {}
            };
          })
          .directive('directive3', function() {
            return {
              template: 'I am {{ctrl1.name}}'
            };
          });
    </script>
  </head>

  <body ng-app='myApp'>
    <directive1>
      <directive2>
        <directive3>
        </directive3>
      </directive2>
    </directive1>
  </body>

</html>

The output of both the codes is - I am Directive1 which shows that directive3 inherits the scope of directive1(it won't access the scope of directive2 since it has an isolated scope) which proved me wrong in assuming that an isolated scope would break the inheritance chain between its parent directive and its child directives and thus none of its child directive would be able to access the scope of any of its ancestor directives.

Am I missing something here or is my concept of scope inheritance completely wrong?


Solution

  • The output <...> proved me wrong in assuming that an isolated scope would break the inheritance chain between its parent directive and its child directives

    The proof itself is wrong. This behaviour is specific to template-less directives and is similar to transclusion. In the code above directive1 has no own scope, and $scope.name = 'Directive1' is set on root scope. And both directive1 and directive2 are compiled with root scope because they have no templates and no own scopes.

    The said assumption will be correct if directives have their own templates, e.g.:

      .directive('directive2', function() {
        return {
          template: '<directive3>'
          controller: ['$scope', function($scope) {
            $scope.name = 'Directive2';
          }],
          scope: {}
        };
      })