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

Commit cde6a9b

Browse files
mzdunek93petebacondarwin
authored andcommitted
fix(): fix scoping for transclusion directives inside replace directive
Closes #12975 Closes #12936
1 parent fe11265 commit cde6a9b

File tree

2 files changed

+77
-7
lines changed

2 files changed

+77
-7
lines changed

src/ng/compile.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
12921292
return function publicLinkFn(scope, cloneConnectFn, options) {
12931293
assertArg(scope, 'scope');
12941294

1295+
if (previousCompileContext && previousCompileContext.needsNewScope) {
1296+
scope = scope.$parent.$new();
1297+
}
1298+
12951299
options = options || {};
12961300
var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
12971301
transcludeControllers = options.transcludeControllers,
@@ -1875,7 +1879,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
18751879
}
18761880

18771881
$compileNode.empty(); // clear contents
1878-
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn);
1882+
childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined, undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope});
18791883
childTranscludeFn.$$slots = slots;
18801884
}
18811885
}
@@ -1918,8 +1922,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
19181922
var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
19191923
var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
19201924

1921-
if (newIsolateScopeDirective) {
1922-
markDirectivesAsIsolate(templateDirectives);
1925+
if (newIsolateScopeDirective || newScopeDirective) {
1926+
// The original directive caused the current element to be replaced but this element
1927+
// also needs to have a new scope, so we need to tell the template directives
1928+
// that they would need to get their scope from further up, if they require transclusion
1929+
markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective);
19231930
}
19241931
directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
19251932
mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
@@ -2214,10 +2221,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
22142221
}
22152222
}
22162223

2217-
function markDirectivesAsIsolate(directives) {
2218-
// mark all directives as needing isolate scope.
2224+
// Depending upon the context in which a directive finds itself it might need to have a new isolated
2225+
// or child scope created. For instance:
2226+
// * if the directive has been pulled into a template because another directive with a higher priority
2227+
// asked for element transclusion
2228+
// * if the directive itself asks for transclusion but it is at the root of a template and the original
2229+
// element was replaced. See https://github.com/angular/angular.js/issues/12936
2230+
function markDirectiveScope(directives, isolateScope, newScope) {
22192231
for (var j = 0, jj = directives.length; j < jj; j++) {
2220-
directives[j] = inherit(directives[j], {$$isolateScope: true});
2232+
directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope});
22212233
}
22222234
}
22232235

@@ -2364,7 +2376,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
23642376
var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
23652377

23662378
if (isObject(origAsyncDirective.scope)) {
2367-
markDirectivesAsIsolate(templateDirectives);
2379+
// the original directive that caused the template to be loaded async required
2380+
// an isolate scope
2381+
markDirectiveScope(templateDirectives, true);
23682382
}
23692383
directives = templateDirectives.concat(directives);
23702384
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);

test/ng/compileSpec.js

+56
Original file line numberDiff line numberDiff line change
@@ -5636,6 +5636,62 @@ describe('$compile', function() {
56365636
});
56375637
});
56385638

5639+
//see issue https://github.com/angular/angular.js/issues/12936
5640+
it('should use the proper scope when being the root element of a replaced directive', function() {
5641+
module(function() {
5642+
directive('isolate', valueFn({
5643+
scope: {},
5644+
replace: true,
5645+
template: '<div trans>{{x}}</div>',
5646+
link: function(scope, element, attr, ctrl) {
5647+
scope.x = 'iso';
5648+
}
5649+
}));
5650+
directive('trans', valueFn({
5651+
transclude: 'content',
5652+
link: function(scope, element, attr, ctrl, $transclude) {
5653+
$transclude(function(clone) {
5654+
element.append(clone);
5655+
});
5656+
}
5657+
}));
5658+
});
5659+
inject(function($rootScope, $compile) {
5660+
element = $compile('<isolate></isolate>')($rootScope);
5661+
$rootScope.x = 'root';
5662+
$rootScope.$apply();
5663+
expect(element.text()).toEqual('iso');
5664+
});
5665+
});
5666+
5667+
5668+
//see issue https://github.com/angular/angular.js/issues/12936
5669+
it('should use the proper scope when being the root element of a replaced directive with child scope', function() {
5670+
module(function() {
5671+
directive('child', valueFn({
5672+
scope: true,
5673+
replace: true,
5674+
template: '<div trans>{{x}}</div>',
5675+
link: function(scope, element, attr, ctrl) {
5676+
scope.x = 'child';
5677+
}
5678+
}));
5679+
directive('trans', valueFn({
5680+
transclude: 'content',
5681+
link: function(scope, element, attr, ctrl, $transclude) {
5682+
$transclude(function(clone) {
5683+
element.append(clone);
5684+
});
5685+
}
5686+
}));
5687+
});
5688+
inject(function($rootScope, $compile) {
5689+
element = $compile('<child></child>')($rootScope);
5690+
$rootScope.x = 'root';
5691+
$rootScope.$apply();
5692+
expect(element.text()).toEqual('child');
5693+
});
5694+
});
56395695

56405696

56415697
it('should not leak if two "element" transclusions are on the same element (with debug info)', function() {

0 commit comments

Comments
 (0)