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

Commit 83194e6

Browse files
fix($compile): fix nested isolated transclude directives
Closes #1809 Closes #7499
1 parent bcab5ac commit 83194e6

File tree

2 files changed

+81
-4
lines changed

2 files changed

+81
-4
lines changed

src/ng/compile.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
964964
// or
965965
// - there is no parentBoundTranscludeFn already and a transcludeFn was passed in
966966
if ( nodeLinkFn.transcludeOnThisElement || (!parentBoundTranscludeFn && transcludeFn) ) {
967-
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn);
967+
childBoundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn, parentBoundTranscludeFn);
968968
} else {
969969
childBoundTranscludeFn = parentBoundTranscludeFn;
970970
}
@@ -978,8 +978,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
978978
}
979979
}
980980

981-
function createBoundTranscludeFn(scope, transcludeFn) {
982-
return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
981+
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) {
982+
983+
// If there is a previous boundTransclude function and it has a transclusionScope then
984+
// use this instead of the current scope
985+
scope = previousBoundTranscludeFn && previousBoundTranscludeFn.transclusionScope || scope;
986+
987+
var boundTranscludeFn = function(transcludedScope, cloneFn, controllers) {
983988
var scopeCreated = false;
984989

985990
if (!transcludedScope) {
@@ -994,6 +999,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
994999
}
9951000
return clone;
9961001
};
1002+
1003+
// Store the transclusionScope for nested transclusions
1004+
boundTranscludeFn.transclusionScope = scope;
1005+
1006+
return boundTranscludeFn;
9971007
}
9981008

9991009
/**
@@ -1767,7 +1777,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17671777
safeAddClass(jqLite(linkNode), oldClasses);
17681778
}
17691779
if (afterTemplateNodeLinkFn.transclude) {
1770-
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
1780+
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn);
17711781
} else {
17721782
childBoundTranscludeFn = boundTranscludeFn;
17731783
}

test/ng/compileSpec.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4185,6 +4185,73 @@ describe('$compile', function() {
41854185
});
41864186

41874187

4188+
describe('nested isolated scope transcludes', function() {
4189+
beforeEach(module(function($compileProvider) {
4190+
4191+
$compileProvider.directive('trans', valueFn({
4192+
restrict: 'E',
4193+
template: '<div ng-transclude></div>',
4194+
transclude: true
4195+
}));
4196+
4197+
$compileProvider.directive('transAsync', valueFn({
4198+
restrict: 'E',
4199+
templateUrl: 'transAsync',
4200+
transclude: true
4201+
}));
4202+
4203+
$compileProvider.directive('iso', valueFn({
4204+
restrict: 'E',
4205+
transclude: true,
4206+
template: '<trans><span ng-transclude></span></trans>',
4207+
scope: {}
4208+
}));
4209+
$compileProvider.directive('isoAsync1', valueFn({
4210+
restrict: 'E',
4211+
transclude: true,
4212+
template: '<trans-async><span ng-transclude></span></trans-async>',
4213+
scope: {}
4214+
}));
4215+
$compileProvider.directive('isoAsync2', valueFn({
4216+
restrict: 'E',
4217+
transclude: true,
4218+
templateUrl: 'isoAsync',
4219+
scope: {}
4220+
}));
4221+
}));
4222+
4223+
beforeEach(inject(function($templateCache) {
4224+
$templateCache.put('transAsync', '<div ng-transclude></div>');
4225+
$templateCache.put('isoAsync', '<trans-async><span ng-transclude></span></trans-async>');
4226+
}));
4227+
4228+
4229+
it('should pass the outer scope to the transclude on the isolated template sync-sync', inject(function($compile, $rootScope) {
4230+
4231+
$rootScope.val = 'transcluded content';
4232+
element = $compile('<iso><span ng-bind="val"></span></iso>')($rootScope);
4233+
$rootScope.$digest();
4234+
expect(element.text()).toEqual('transcluded content');
4235+
}));
4236+
4237+
it('should pass the outer scope to the transclude on the isolated template async-sync', inject(function($compile, $rootScope) {
4238+
4239+
$rootScope.val = 'transcluded content';
4240+
element = $compile('<iso-async1><span ng-bind="val"></span></iso-async1>')($rootScope);
4241+
$rootScope.$digest();
4242+
expect(element.text()).toEqual('transcluded content');
4243+
}));
4244+
4245+
it('should pass the outer scope to the transclude on the isolated template async-async', inject(function($compile, $rootScope) {
4246+
4247+
$rootScope.val = 'transcluded content';
4248+
element = $compile('<iso-async2><span ng-bind="val"></span></iso-async2>')($rootScope);
4249+
$rootScope.$digest();
4250+
expect(element.text()).toEqual('transcluded content');
4251+
}));
4252+
4253+
});
4254+
41884255
describe('multiple siblings receiving transclusion', function() {
41894256

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

0 commit comments

Comments
 (0)