Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 4f03dc5

Browse files
vojtajinaIgorMinar
authored andcommitted
fix($compile): pass transcludeFn down to nested transclude directives
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. Fixes #7240 Closes #7387
1 parent d16102f commit 4f03dc5

File tree

2 files changed

+86
-9
lines changed

2 files changed

+86
-9
lines changed

src/ng/compile.js

+14-9
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
941941
return linkFnFound ? compositeLinkFn : null;
942942

943943
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
944-
var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
944+
var nodeLinkFn, childLinkFn, node, $node, childScope, i, ii, n;
945945

946946
// copy nodeList so that linking doesn't break due to live list updates.
947947
var nodeListLength = nodeList.length,
@@ -963,14 +963,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
963963
} else {
964964
childScope = scope;
965965
}
966-
childTranscludeFn = nodeLinkFn.transclude;
967-
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
968-
nodeLinkFn(childLinkFn, childScope, node, $rootElement,
969-
createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
970-
);
971-
} else {
972-
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
966+
967+
// We need to create a new boundTranscludeFn if
968+
// - a directive on this element wants to transclude
969+
// or
970+
// - there is no boundTranscludeFn already and a transcludeFn was passed in
971+
if ( nodeLinkFn.transcludeOnThisElement || (!boundTranscludeFn && transcludeFn) ) {
972+
boundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn);
973973
}
974+
975+
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
976+
974977
} else if (childLinkFn) {
975978
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
976979
}
@@ -1346,7 +1349,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13461349
}
13471350

13481351
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
1349-
nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
1352+
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
1353+
nodeLinkFn.transclude = childTranscludeFn;
1354+
13501355
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
13511356

13521357
// might be normal or delayed nodeLinkFn depending on if templateUrl is present

test/ng/compileSpec.js

+72
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,78 @@ describe('$compile', function() {
14971497
));
14981498

14991499

1500+
describe('nested transcludes', function() {
1501+
1502+
beforeEach(module(function($compileProvider) {
1503+
1504+
$compileProvider.directive('noop', valueFn({}));
1505+
1506+
$compileProvider.directive('sync', valueFn({
1507+
template: '<div ng-transclude></div>',
1508+
transclude: true
1509+
}));
1510+
1511+
$compileProvider.directive('async', valueFn({
1512+
templateUrl: 'async',
1513+
transclude: true
1514+
}));
1515+
1516+
$compileProvider.directive('syncSync', valueFn({
1517+
template: '<div noop><div sync><div ng-transclude></div></div></div>',
1518+
transclude: true
1519+
}));
1520+
1521+
$compileProvider.directive('syncAsync', valueFn({
1522+
template: '<div noop><div async><div ng-transclude></div></div></div>',
1523+
transclude: true
1524+
}));
1525+
1526+
$compileProvider.directive('asyncSync', valueFn({
1527+
templateUrl: 'asyncSync',
1528+
transclude: true
1529+
}));
1530+
1531+
$compileProvider.directive('asyncAsync', valueFn({
1532+
templateUrl: 'asyncAsync',
1533+
transclude: true
1534+
}));
1535+
1536+
}));
1537+
1538+
beforeEach(inject(function($templateCache) {
1539+
$templateCache.put('async', '<div ng-transclude></div>');
1540+
$templateCache.put('asyncSync', '<div noop><div sync><div ng-transclude></div></div></div>');
1541+
$templateCache.put('asyncAsync', '<div noop><div async><div ng-transclude></div></div></div>');
1542+
}));
1543+
1544+
1545+
it('should allow nested transclude directives with sync template containing sync template', inject(function($compile, $rootScope) {
1546+
element = $compile('<div sync-sync>transcluded content</div>')($rootScope);
1547+
$rootScope.$digest();
1548+
expect(element.text().trim()).toEqual('transcluded content');
1549+
}));
1550+
1551+
it('should allow nested transclude directives with sync template containing async template', inject(function($compile, $rootScope) {
1552+
element = $compile('<div sync-async>transcluded content</div>')($rootScope);
1553+
$rootScope.$digest();
1554+
expect(element.text().trim()).toEqual('transcluded content');
1555+
}));
1556+
1557+
it('should allow nested transclude directives with async template containing sync template', inject(function($compile, $rootScope) {
1558+
element = $compile('<div async-sync>transcluded content</div>')($rootScope);
1559+
$rootScope.$digest();
1560+
expect(element.text().trim()).toEqual('transcluded content');
1561+
}));
1562+
1563+
it('should allow nested transclude directives with async template containing asynch template', inject(function($compile, $rootScope) {
1564+
element = $compile('<div async-async>transcluded content</div>')($rootScope);
1565+
$rootScope.$digest();
1566+
expect(element.text().trim()).toEqual('transcluded content');
1567+
}));
1568+
});
1569+
1570+
1571+
15001572
it("should fail if replacing and template doesn't have a single root element", function() {
15011573
module(function($exceptionHandlerProvider) {
15021574
$exceptionHandlerProvider.mode('log');

0 commit comments

Comments
 (0)