-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Nested iso transcludes #7499
Nested iso transcludes #7499
Conversation
Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
Things are never as easy as they seem.
I think that the second and third points may be related to both directives using |
@@ -89,7 +89,7 @@ var ngIfDirective = ['$animate', function($animate) { | |||
|
|||
if (toBoolean(value)) { | |||
if (!childScope) { | |||
childScope = $scope.$new(); | |||
childScope = $transclude.transclusionScope.$new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't look right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a way for directives to be able to create a new scope that is the child of the correct scope. $transclude
is bound to a scope that may be different to the scope of the directive.
For instance if the ng-if
is in a template of a directive that declares isolated scope, but the transclusion comes from outside the isolated scope. In this case we should not be using a child of $scope
.
E.g.
If you have a directive, iso
, that transcludes and has isolated scope:
<iso><span ng-bind="val"></span></iso>
where the template of iso
contains:
<div ng-if="true"><div ng-transclude></div></div>
Then the transcluded content will be a child of $rootScope
but the scope of the ng-if
is a child of the isolated scope. So you cannot use the scope of ng-if when you want to link, clone and inject the transcluded content.
The $transclude
function in ng-if
is bound to the correct scope so if we use that directly then all is well, except in the case of ng-if
and other directives that want to add and remove copies of the transcluded content, we want to create a new scope that we can destroy later.
I thought about creating new child scopes of the transclude scope if we are cloning the transclude, which would give us the correct scope but we need a way to then reference this scope in order to be able to destroy it later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I just realised that if you are cloning the transclude then a new scope is defined that is bound correctly and that it also sets up an event handler to destroy the scope when the element gets destroyed so this fixes this problem. We just remove passing in a scope to the $transclude function altogether.
This new set of commits fixes this more cleanly but there are still problems when directives transclude element (or possibly when they async replace their element). |
childScope = $scope.$new(); | ||
$transclude(childScope, function (clone) { | ||
if (!block ) { | ||
$transclude(function (clone) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we don't pass in a scope but leave $transclude to make a new (correctly bound) scope for us.
If you have two directives that both expect to receive transcluded content the outer directive works but the inner directive never receives a transclusion function. This only failed if the first transclude directive was not the first directive found in compilation. Handles the regression identified in e994259 Fixes angular#7240 Closes angular#7387
Fixes #1809