fix(ngSwitch): properly support case labels with different numbers of transclude fns

Due to a regression introduced several releases ago, the ability for multiple transclude functions
to work correctly changed, as they would break if different case labels had different numbers of
transclude functions.

This CL corrects this by not assuming that previous elements and scope count have the same length.

Fixes 7372
Closes 7373
This commit is contained in:
Caitlin Potter
2014-05-06 22:57:31 -04:00
parent 31bdb60f0a
commit 32aa491588
2 changed files with 40 additions and 25 deletions
+17 -25
View File
@@ -138,37 +138,29 @@ var ngSwitchDirective = ['$animate', function($animate) {
}],
link: function(scope, element, attr, ngSwitchController) {
var watchExpr = attr.ngSwitch || attr.on,
selectedTranscludes,
selectedElements,
previousElements,
selectedTranscludes = [],
selectedElements = [],
previousElements = [],
selectedScopes = [];
scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
var i, ii = selectedScopes.length;
if(ii > 0) {
if(previousElements) {
for (i = 0; i < ii; i++) {
previousElements[i].remove();
}
previousElements = null;
}
var i, ii;
for (i = 0, ii = previousElements.length; i < ii; ++i) {
previousElements[i].remove();
}
previousElements.length = 0;
previousElements = [];
for (i= 0; i<ii; i++) {
var selected = selectedElements[i];
selectedScopes[i].$destroy();
previousElements[i] = selected;
$animate.leave(selected, function() {
previousElements.splice(i, 1);
if(previousElements.length === 0) {
previousElements = null;
}
});
}
for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
var selected = selectedElements[i];
selectedScopes[i].$destroy();
previousElements[i] = selected;
$animate.leave(selected, function() {
previousElements.splice(i, 1);
});
}
selectedElements = [];
selectedScopes = [];
selectedElements.length = 0;
selectedScopes.length = 0;
if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
scope.$eval(attr.change);
+23
View File
@@ -212,6 +212,29 @@ describe('ngSwitch', function() {
// element now contains only empty repeater. this element is dealocated by local afterEach.
// afterwards a global afterEach will check for leaks in jq data cache object
}));
it('should properly support case labels with different numbers of transclude fns', inject(function($rootScope, $compile) {
element = $compile(
'<div ng-switch="mode">' +
'<p ng-switch-when="a">Block1</p>' +
'<p ng-switch-when="a">Block2</p>' +
'<a href ng-switch-when="b">a</a>' +
'</div>'
)($rootScope);
$rootScope.$apply('mode = "a"');
expect(element.children().length).toBe(2);
$rootScope.$apply('mode = "b"');
expect(element.children().length).toBe(1);
$rootScope.$apply('mode = "a"');
expect(element.children().length).toBe(2);
$rootScope.$apply('mode = "b"');
expect(element.children().length).toBe(1);
}));
});
describe('ngSwitch animations', function() {