Peeyush Kushwaha
Peeyush Kushwaha

Reputation: 3623

AngularJS : Child directive scope to inherit from parent directive isolated scope?

If a and b are my directives such that b is a child element of a :

<a>
  <b></b>
</a>

Is it possible that if a has an isolated scope, then b could inherit from it?

Example js:

app.directive('a', function () {
  return {
    restrict: 'E',
    scope: {},
    controller: function ($scope) {
      $scope.prop1 = ...
    }
  }
});
app.directive('b', function () {
  return {
    restrict: 'E',
    controller: function ($scope) {
      //how to access $scope.prop1 here?
    }
  }
});

With this, I'm trying to make directives that are reusable and are supposed to be used as nested within each other.

I know that I can require the controller of a on directive b to access it within the link function of b as one way to share the data between controllers, but that approach isn't working very well if I have more than one level of nesting.

Upvotes: 2

Views: 1535

Answers (1)

New Dev
New Dev

Reputation: 49590

This is where you need to use the manual transclusion function. If the parent directive has an isolate scope, the child DOM elements (and their directives) would not inherit from it (only, if they were in its template).

When you transclude, you can specify the scope explicitly:

.directive("a", function(){
  return {
    scope: {},
    transclude: true,
    link: function(scope, element, attrs, ctrls, transclude){
       var newScope = scope.$new();
       transclude(newScope, function(clone){
         element.append(clone);
       })
    }
  };
});

You should note, though, that although the above would work (in the sense that the child directive's scope would inherit the parent's isolate scope), it is also a somewhat confusing experience to the user of your directive.

To see why, imagine that a exposes some $innerProp on its scope. The user of a now has to know that such property is "magically" available. This makes the HTML less readable without knowing a lot about a:

<a>
  <b item="$innerProp"></b>
</a>

Addendum

Depending on your use case, there might be other approaches that are more suitable. The above approach works better when a and b are independent, and when a uses its contents to allow its user to specify some template.

If b is only (or mostly) used as a child of a, then it should require it. a can expose whatever it needs via its controller API to b.

Lastly, if a has a well-defined structure, then it should use its template to specify b. In your example, this could easily be achieved with a template.

Upvotes: 2

Related Questions