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

Commit 5425777

Browse files
committed
fix($compile): do not bind twice transclude functions
Do not double bind transclude functions that are passed to the compiler that were already bound Worked with @dlongley on the implementation Closes #9413
1 parent 57ee249 commit 5425777

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

src/ng/compile.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -1317,6 +1317,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13171317

13181318
function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn, elementTransclusion) {
13191319

1320+
// preserve previously bound scope
1321+
if (transcludeFn.$$bound) {
1322+
scope = transcludeFn.$$bound;
1323+
}
1324+
13201325
var boundTranscludeFn = function(transcludedScope, cloneFn, futureParentElement, controllers, containingScope) {
13211326

13221327
if (!transcludedScope) {
@@ -1327,6 +1332,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
13271332
return transcludeFn(transcludedScope, cloneFn, futureParentElement, controllers, previousBoundTranscludeFn);
13281333
};
13291334

1335+
boundTranscludeFn.$$bound = scope;
1336+
13301337
return boundTranscludeFn;
13311338
}
13321339

@@ -1793,7 +1800,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
17931800
isolateScope = scope.$new(true);
17941801
}
17951802

1796-
transcludeFn = boundTranscludeFn && controllersBoundTransclude;
1803+
if (boundTranscludeFn) {
1804+
transcludeFn = controllersBoundTransclude;
1805+
transcludeFn.$$bound = boundTranscludeFn.$$bound;
1806+
}
17971807
if (controllerDirectives) {
17981808
// TODO: merge `controllers` and `elementControllers` into single object.
17991809
controllers = {};
@@ -1953,7 +1963,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
19531963
var transcludeControllers;
19541964

19551965
// No scope passed in:
1956-
if (!isScope(scope)) {
1966+
if (!isScope(scope) && !isUndefined(scope)) {
19571967
futureParentElement = cloneAttachFn;
19581968
cloneAttachFn = scope;
19591969
scope = undefined;

test/ng/compileSpec.js

+73
Original file line numberDiff line numberDiff line change
@@ -5124,6 +5124,79 @@ describe('$compile', function() {
51245124
});
51255125

51265126

5127+
it('should bind the tranclude function to the original scope when used ' +
5128+
'in a future `$compile` call', function() {
5129+
5130+
function countScopes($rootScope) {
5131+
return [$rootScope].concat(
5132+
getChildScopes($rootScope)
5133+
).length;
5134+
}
5135+
5136+
function getChildScopes(scope) {
5137+
var children = [];
5138+
if (!scope.$$childHead) { return children; }
5139+
var childScope = scope.$$childHead;
5140+
do {
5141+
children.push(childScope);
5142+
children = children.concat(getChildScopes(childScope));
5143+
} while ((childScope = childScope.$$nextSibling));
5144+
return children;
5145+
}
5146+
5147+
5148+
module(function() {
5149+
directive('isolate', function() {
5150+
return {
5151+
scope: {}
5152+
};
5153+
});
5154+
directive('usesTransclude', function($compile) {
5155+
return {
5156+
scope: {foo: '='},
5157+
transclude: true,
5158+
template: '<div><div ng-if="foo"><div ng-transclude></div></div></div>',
5159+
compile: function(tElement, tAttrs) {
5160+
var content = tElement.contents();
5161+
tElement.empty();
5162+
return function(scope, element, attrs, ctrls, transcludeFn) {
5163+
element.append(content);
5164+
$compile(content, transcludeFn)(scope);
5165+
};
5166+
}
5167+
};
5168+
});
5169+
});
5170+
inject(function($compile) {
5171+
element = $compile(
5172+
'<div>' +
5173+
'<div ng-init="outer=true"></div>' +
5174+
'<div uses-transclude foo="foo">' +
5175+
'<div uses-transclude foo="foo">' +
5176+
'<span ng-if="outer">Success</span><span ng-if="!outer">Error</span>' +
5177+
'</div>' +
5178+
'</div>' +
5179+
'</div>')($rootScope);
5180+
$rootScope.foo = false;
5181+
$rootScope.$digest();
5182+
expect(countScopes($rootScope)).toBe(2);
5183+
expect(element.text()).toBe('');
5184+
$rootScope.foo = true;
5185+
$rootScope.$digest();
5186+
expect(countScopes($rootScope)).toBe(8);
5187+
expect(element.text()).toBe('Success');
5188+
$rootScope.foo = false;
5189+
$rootScope.$digest();
5190+
expect(countScopes($rootScope)).toBe(2);
5191+
expect(element.text()).toBe('');
5192+
$rootScope.foo = true;
5193+
$rootScope.$digest();
5194+
expect(countScopes($rootScope)).toBe(8);
5195+
expect(element.text()).toBe('Success');
5196+
});
5197+
});
5198+
5199+
51275200
// see issue https://github.com/angular/angular.js/issues/9095
51285201
describe('removing a transcluded element', function() {
51295202

0 commit comments

Comments
 (0)