1
votes

I am trying to make a transitive transclusion, or call it “directive inception”.

I made this example to illustrate what I am trying to do:

http://plnkr.co/edit/0hFFHknDps2krtK1D9ud?p=preview

The directive “first” wraps the directive “second” in its template and the two of them use transclusion. What I want to do is to bind a value from a controller to the html that is a child of the “first” directive. So I wanted my example to display:

<h1>Chained transclusions test</h1>
<div>
  <h2>First directive</h2>
  <div>
    <h2>Second directive</h2>
    <div>Controller hello</div>
   </div>
</div>

Obviously that is not what I got. I tried to analyze the scope with the developer tool and I was surprised by the result scope tree:

the result trees

I thought angularJS would create a new scope when using the transclude feature in a directive. And that this scope would be a non isolate sibling of my directive isolate scope. But I cannot see any sibling of my first directive scope (although it uses transclude). Plus, every children of my “first” directive has a scope isolated from the controller scope since the “first” directive scope is an isolated one.

I don’t understand the behavior here.

Is the transclude inclusion completely forbidden in angularJS ? Is it possible to create a directive with transclusion, that wraps another directive that uses transclusion ?

It seems to me that this is the whole power behind web components, the fact that transclusion or any other special caracteristics should be seen as “implementation detail”, and the component should be able to use other directives that hide their own implementation details.

1
Did my answer help you to solve your problem? If not, provide comments or update this question with edits.Marc Kline

1 Answers

0
votes

Without getting into the details of scope creation when using isolate scope with transclusion... it is possible to nest transclusions, but in your example, you need to make scope.controllerMsg available to the first directive's isolate scope:

JS:

app.directive('first', function(){
    return {
        ...
        scope: { controllerMsg: '=text'},
        ...
    }
});

HTML:

<first text="controllerMsg">
    {{controllerMsg}}
</first>

Demo