Skip to content

Commit 2ae678f

Browse files
committed
fix($compile): link async+replace element transclusion directives with comment element
Previously, element transclusion directives would not receive a comment node in their link functions when they were the root of an asynchronous replace template. This would cause duplicate elements to appear in an ng-if expression within ng-repeat. Closes angular#6006
1 parent 19ba651 commit 2ae678f

File tree

2 files changed

+65
-5
lines changed

2 files changed

+65
-5
lines changed

src/ng/compile.js

+17-5
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
12131213
compileNode = $compileNode[0];
12141214
replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode);
12151215

1216+
12161217
childTranscludeFn = compile($template, transcludeFn, terminalPriority,
12171218
replaceDirective && replaceDirective.name, {
12181219
// Don't pass in:
@@ -1662,7 +1663,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16621663

16631664
$http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
16641665
success(function(content) {
1665-
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
1666+
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn, replaceTransclude;
16661667

16671668
content = denormalizeTemplate(content);
16681669

@@ -1685,6 +1686,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16851686
}
16861687
directives = templateDirectives.concat(directives);
16871688
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
1689+
for (var i=0, ii=directives.length; i<ii; ++i) {
1690+
if (directives[i].transclude === 'element') {
1691+
replaceTransclude = true;
1692+
}
1693+
}
16881694
} else {
16891695
compileNode = beforeTemplateCompileNode;
16901696
$compileNode.html(content);
@@ -1712,12 +1718,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17121718

17131719
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
17141720
var oldClasses = beforeTemplateLinkNode.className;
1715-
// it was cloned therefore we have to clone as well.
1716-
linkNode = jqLiteClone(compileNode);
1721+
1722+
if (!replaceTransclude) {
1723+
// it was cloned therefore we have to clone as well.
1724+
linkNode = jqLiteClone(compileNode);
1725+
}
1726+
17171727
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
17181728

1719-
// Copy in CSS classes from original node
1720-
safeAddClass(jqLite(linkNode), oldClasses);
1729+
if (isDefined(oldClasses)) {
1730+
// Copy in CSS classes from original node
1731+
safeAddClass(jqLite(linkNode), oldClasses);
1732+
}
17211733
}
17221734
if (afterTemplateNodeLinkFn.transclude) {
17231735
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);

test/ng/compileSpec.js

+48
Original file line numberDiff line numberDiff line change
@@ -3972,6 +3972,54 @@ describe('$compile', function() {
39723972
});
39733973
});
39743974

3975+
// issue #6006
3976+
it('should link directive with $element as a comment node', function() {
3977+
module(function($provide) {
3978+
directive('innerAgain', function(log) {
3979+
return {
3980+
transclude: 'element',
3981+
link: function(scope, element, attr, controllers, transclude) {
3982+
log('innerAgain:'+lowercase(nodeName_(element)));
3983+
transclude(scope, function(clone) {
3984+
element.parent().append(clone);
3985+
});
3986+
}
3987+
};
3988+
});
3989+
directive('inner', function(log) {
3990+
return {
3991+
replace: true,
3992+
templateUrl: 'inner.html',
3993+
link: function(scope, element) {
3994+
log('inner:'+lowercase(nodeName_(element)));
3995+
}
3996+
};
3997+
});
3998+
directive('outer', function(log) {
3999+
return {
4000+
transclude: 'element',
4001+
link: function(scope, element, attrs, controllers, transclude) {
4002+
log('outer:'+lowercase(nodeName_(element)));
4003+
transclude(scope, function(clone) {
4004+
element.parent().append(clone);
4005+
});
4006+
}
4007+
};
4008+
});
4009+
});
4010+
inject(function(log, $compile, $rootScope, $templateCache) {
4011+
$templateCache.put('inner.html', '<div inner-again><p>Content</p></div>');
4012+
element = $compile('<div><div outer><div inner></div></div></div>')($rootScope);
4013+
$rootScope.$digest();
4014+
var child = element.children();
4015+
4016+
expect(log.toArray()).toEqual(["outer:#comment", "innerAgain:#comment", "inner:#comment"]);
4017+
expect(child.length).toBe(1);
4018+
expect(child.contents().length).toBe(2);
4019+
expect(lowercase(nodeName_(child.contents().eq(0)))).toBe('#comment');
4020+
expect(lowercase(nodeName_(child.contents().eq(1)))).toBe('div');
4021+
});
4022+
});
39754023
});
39764024

39774025
it('should safely create transclude comment node and not break with "-->"',

0 commit comments

Comments
 (0)