Skip to content

Commit b2b9ef1

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 b2b9ef1

File tree

2 files changed

+64
-5
lines changed

2 files changed

+64
-5
lines changed

src/ng/compile.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16621662

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

16671667
content = denormalizeTemplate(content);
16681668

@@ -1685,6 +1685,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16851685
}
16861686
directives = templateDirectives.concat(directives);
16871687
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
1688+
for (var i=0, ii=directives.length; i<ii; ++i) {
1689+
if (directives[i].transclude === 'element') {
1690+
replaceTransclude = true;
1691+
}
1692+
}
16881693
} else {
16891694
compileNode = beforeTemplateCompileNode;
16901695
$compileNode.html(content);
@@ -1712,12 +1717,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17121717

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

1719-
// Copy in CSS classes from original node
1720-
safeAddClass(jqLite(linkNode), oldClasses);
1728+
if (isDefined(oldClasses)) {
1729+
// Copy in CSS classes from original node
1730+
safeAddClass(jqLite(linkNode), oldClasses);
1731+
}
17211732
}
17221733
if (afterTemplateNodeLinkFn.transclude) {
17231734
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)