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

Commit bb93109

Browse files
petebacondarwincaitp
authored andcommitted
fix($compile): fix nested isolated transclude directives
Closes #1809 Closes #7499
1 parent 30279d7 commit bb93109

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

src/ng/compile.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
947947
// or
948948
// - there is no parentBoundTranscludeFn already and a transcludeFn was passed in
949949
if ( nodeLinkFn.transcludeOnThisElement || (!parentBoundTranscludeFn && transcludeFn) ) {
950-
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn);
950+
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn, parentBoundTranscludeFn);
951951
} else {
952952
childBoundTranscludeFn = parentBoundTranscludeFn;
953953
}
@@ -961,8 +961,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
961961
}
962962
}
963963

964-
function createBoundTranscludeFn(scope, transcludeFn) {
965-
return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
964+
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
965+
966+
// If there is a previous boundTransclude function and it has a transclusionScope then
967+
// use this instead of the current scope
968+
scope = previousBoundTranscludeFn && previousBoundTranscludeFn.transclusionScope || scope;
969+
970+
var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
966971
var scopeCreated = false;
967972

968973
if (!transcludedScope) {
@@ -977,6 +982,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
977982
}
978983
return clone;
979984
};
985+
986+
// Store the transclusionScope for nested transclusions
987+
boundTranscludeFn.transclusionScope = scope;
988+
989+
return boundTranscludeFn;
980990
}
981991

982992
/**
@@ -1749,7 +1759,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17491759
safeAddClass(jqLite(linkNode), oldClasses);
17501760
}
17511761
if (afterTemplateNodeLinkFn.transclude) {
1752-
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
1762+
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
17531763
} else {
17541764
childBoundTranscludeFn = boundTranscludeFn;
17551765
}

test/ng/compileSpec.js

+67
Original file line numberDiff line numberDiff line change
@@ -4055,6 +4055,73 @@ describe('$compile', function() {
40554055
});
40564056

40574057

4058+
describe('nested isolated scope transcludes', function() {
4059+
beforeEach(module(function($compileProvider) {
4060+
4061+
$compileProvider.directive('trans', valueFn({
4062+
restrict: 'E',
4063+
template: '<div ng-transclude></div>',
4064+
transclude: true
4065+
}));
4066+
4067+
$compileProvider.directive('transAsync', valueFn({
4068+
restrict: 'E',
4069+
templateUrl: 'transAsync',
4070+
transclude: true
4071+
}));
4072+
4073+
$compileProvider.directive('iso', valueFn({
4074+
restrict: 'E',
4075+
transclude: true,
4076+
template: '<trans><span ng-transclude></span></trans>',
4077+
scope: {}
4078+
}));
4079+
$compileProvider.directive('isoAsync1', valueFn({
4080+
restrict: 'E',
4081+
transclude: true,
4082+
template: '<trans-async><span ng-transclude></span></trans-async>',
4083+
scope: {}
4084+
}));
4085+
$compileProvider.directive('isoAsync2', valueFn({
4086+
restrict: 'E',
4087+
transclude: true,
4088+
templateUrl: 'isoAsync',
4089+
scope: {}
4090+
}));
4091+
}));
4092+
4093+
beforeEach(inject(function($templateCache) {
4094+
$templateCache.put('transAsync', '<div ng-transclude></div>');
4095+
$templateCache.put('isoAsync', '<trans-async><span ng-transclude></span></trans-async>');
4096+
}));
4097+
4098+
4099+
it('should pass the outer scope to the transclude on the isolated template sync-sync', inject(function($compile, $rootScope) {
4100+
4101+
$rootScope.val = 'transcluded content';
4102+
element = $compile('<iso><span ng-bind="val"></span></iso>')($rootScope);
4103+
$rootScope.$digest();
4104+
expect(element.text()).toEqual('transcluded content');
4105+
}));
4106+
4107+
it('should pass the outer scope to the transclude on the isolated template async-sync', inject(function($compile, $rootScope) {
4108+
4109+
$rootScope.val = 'transcluded content';
4110+
element = $compile('<iso-async1><span ng-bind="val"></span></iso-async1>')($rootScope);
4111+
$rootScope.$digest();
4112+
expect(element.text()).toEqual('transcluded content');
4113+
}));
4114+
4115+
it('should pass the outer scope to the transclude on the isolated template async-async', inject(function($compile, $rootScope) {
4116+
4117+
$rootScope.val = 'transcluded content';
4118+
element = $compile('<iso-async2><span ng-bind="val"></span></iso-async2>')($rootScope);
4119+
$rootScope.$digest();
4120+
expect(element.text()).toEqual('transcluded content');
4121+
}));
4122+
4123+
});
4124+
40584125
describe('multiple siblings receiving transclusion', function() {
40594126

40604127
it("should only receive transclude from parent", function() {

0 commit comments

Comments
 (0)