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

Commit

Permalink
fix(ngSwitch): properly support case labels with different numbers of…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
caitp committed May 8, 2014
1 parent 31bdb60 commit 32aa491
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 25 deletions.
42 changes: 17 additions & 25 deletions src/ng/directive/ngSwitch.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 23 additions & 0 deletions test/ng/directive/ngSwitchSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 32aa491

Please sign in to comment.