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

Commit 1138506

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 e76105a commit 1138506

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
@@ -924,7 +924,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
924924
return linkFnFound ? compositeLinkFn : null;
925925

926926
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
927-
var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
927+
var nodeLinkFn, childLinkFn, node, $node, childScope, i, ii, n;
928928

929929
// copy nodeList so that linking doesn't break due to live list updates.
930930
var nodeListLength = nodeList.length,
@@ -946,14 +946,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
946946
} else {
947947
childScope = scope;
948948
}
949-
childTranscludeFn = nodeLinkFn.transclude;
950-
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
951-
nodeLinkFn(childLinkFn, childScope, node, $rootElement,
952-
createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
953-
);
954-
} else {
955-
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
949+
950+
// We need to create a new boundTranscludeFn if
951+
// - a directive on this element wants to transclude
952+
// or
953+
// - there is no boundTranscludeFn already and a transcludeFn was passed in
954+
if ( nodeLinkFn.transcludeOnThisElement || (!boundTranscludeFn && transcludeFn) ) {
955+
boundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn);
956956
}
957+
958+
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
959+
957960
} else if (childLinkFn) {
958961
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
959962
}
@@ -1329,7 +1332,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13291332
}
13301333

13311334
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
1332-
nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
1335+
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
1336+
nodeLinkFn.transclude = childTranscludeFn;
1337+
13331338
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
13341339

13351340
// 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
@@ -1436,6 +1436,78 @@ describe('$compile', function() {
14361436
));
14371437

14381438

1439+
describe('nested transcludes', function() {
1440+
1441+
beforeEach(module(function($compileProvider) {
1442+
1443+
$compileProvider.directive('noop', valueFn({}));
1444+
1445+
$compileProvider.directive('sync', valueFn({
1446+
template: '<div ng-transclude></div>',
1447+
transclude: true
1448+
}));
1449+
1450+
$compileProvider.directive('async', valueFn({
1451+
templateUrl: 'async',
1452+
transclude: true
1453+
}));
1454+
1455+
$compileProvider.directive('syncSync', valueFn({
1456+
template: '<div noop><div sync><div ng-transclude></div></div></div>',
1457+
transclude: true
1458+
}));
1459+
1460+
$compileProvider.directive('syncAsync', valueFn({
1461+
template: '<div noop><div async><div ng-transclude></div></div></div>',
1462+
transclude: true
1463+
}));
1464+
1465+
$compileProvider.directive('asyncSync', valueFn({
1466+
templateUrl: 'asyncSync',
1467+
transclude: true
1468+
}));
1469+
1470+
$compileProvider.directive('asyncAsync', valueFn({
1471+
templateUrl: 'asyncAsync',
1472+
transclude: true
1473+
}));
1474+
1475+
}));
1476+
1477+
beforeEach(inject(function($templateCache) {
1478+
$templateCache.put('async', '<div ng-transclude></div>');
1479+
$templateCache.put('asyncSync', '<div noop><div sync><div ng-transclude></div></div></div>');
1480+
$templateCache.put('asyncAsync', '<div noop><div async><div ng-transclude></div></div></div>');
1481+
}));
1482+
1483+
1484+
it('should allow nested transclude directives with sync template containing sync template', inject(function($compile, $rootScope) {
1485+
element = $compile('<div sync-sync>transcluded content</div>')($rootScope);
1486+
$rootScope.$digest();
1487+
expect(element.text().trim()).toEqual('transcluded content');
1488+
}));
1489+
1490+
it('should allow nested transclude directives with sync template containing async template', inject(function($compile, $rootScope) {
1491+
element = $compile('<div sync-async>transcluded content</div>')($rootScope);
1492+
$rootScope.$digest();
1493+
expect(element.text().trim()).toEqual('transcluded content');
1494+
}));
1495+
1496+
it('should allow nested transclude directives with async template containing sync template', inject(function($compile, $rootScope) {
1497+
element = $compile('<div async-sync>transcluded content</div>')($rootScope);
1498+
$rootScope.$digest();
1499+
expect(element.text().trim()).toEqual('transcluded content');
1500+
}));
1501+
1502+
it('should allow nested transclude directives with async template containing asynch template', inject(function($compile, $rootScope) {
1503+
element = $compile('<div async-async>transcluded content</div>')($rootScope);
1504+
$rootScope.$digest();
1505+
expect(element.text().trim()).toEqual('transcluded content');
1506+
}));
1507+
});
1508+
1509+
1510+
14391511
it("should fail if replacing and template doesn't have a single root element", function() {
14401512
module(function($exceptionHandlerProvider) {
14411513
$exceptionHandlerProvider.mode('log');

0 commit comments

Comments
 (0)