Given a directive (container1
) with transclude and an isolated scope, when the directive is linked then I have these scopes:
Scope 004 <-- scope of the body Scope 005 <-- scope of directive container1 Scope 006 <-- scope of the ng-transclude
I expected:
Scope 004 <-- scope of the body Scope 005 <-- scope of the directive Scope 006 <-- scope of the ng-transclude
If the same directive has a shared scope instead of an isolated scope, I get the expected result.
This causes me a problem because, if the transcluded content contains another directive (component1
) with an isolated scope, I get:
Scope 004 <-- scope of the body Scope 005 <-- scope of the directive Scope 006 <-- scope of the ng-transclude Scope 007 <-- scope of directive component1
I want to use the directives like this:
<container1> <component1 data="objectExposedInContainer1"/> </container1>
But that does not work, inside component1
, $scope.data
is undefined
because objectExposedInContainer1
is not on the right scope.
I have two questions:
ng-transclude
's scope is not a child of its directive's scope if the directive has an isolated scope? Is this a bug?Here is a sample where it does not work: http://plnkr.co/edit/NDmJiRzTF9e5gw8Buht2?p=preview. Because Plunker is built with Anguar, it's hard to debug with Batarang. I recommend downloading the code locally. Comment out line 10
of app.js
to make it work using a shared scope.
Why ng-transclude's scope is not a child of its directive's scope if the directive has an isolated scope?
ng-transclude
designed to allow directives to work with arbitrary content, and isolated scopes are designed to allow directives to encapsulate their data.
If ng-transclude
didn't preserve scopes like that, any arbitrary content that you're transcluding would need to know the implementation details of your directive (i.e. it would need to know what's available on the isolated scope you created).
If it's not a bug, how can a container directive pass data to it's content, if not by setting attributes like I tried.
If the container directive and contained directives are coupled - i.e. you wrote both of them and need them to act together - then they should communicate via a shared controller.
If the container directive is supposed to inject content into the scope of the children (e.g. ng-repeat), then you shouldn't be using an isolated scope.
The angular documentation is quite clear on what the behaviour is supposed to be:
"In a typical setup the widget creates an isolate scope, but the transclusion is not a child, but a sibling of the isolate scope. This makes it possible for the widget to have private state, and the transclusion to be bound to the parent (pre-isolate) scope."
you can manually transclude the child element
link: function(scope, element, attrs, ctrl, transclude) { transclude(scope, function(clone, scope) { element.find('.transclude-placeholder').append(clone); }); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With