Skip to content

Commit 5328ccd

Browse files
committed
fix(ngAnimate): don't normalize classes on follow-up animations to joined animations
This allows follow-up animations to remove a class that is currently being added. Fixes angular#13339 Fixes angular#13380 Closes angular#13414
1 parent 023b777 commit 5328ccd

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

src/ngAnimate/animateQueue.js

+7-11
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,15 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
360360
// so an example would involve a leave animation taking over an enter. Then when
361361
// the postDigest kicks in the enter will be ignored.
362362
var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation);
363-
if (joinAnimationFlag) {
364-
if (existingAnimation.state === RUNNING_STATE) {
365-
normalizeAnimationOptions(element, options);
366-
} else {
367-
applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
363+
if (joinAnimationFlag && existingAnimation.state < RUNNING_STATE) {
364+
applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
368365

369-
event = newAnimation.event = existingAnimation.event;
370-
options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
366+
event = newAnimation.event = existingAnimation.event;
367+
options = mergeAnimationOptions(element, existingAnimation.options, newAnimation.options);
371368

372-
//we return the same runner since only the option values of this animation will
373-
//be fed into the `existingAnimation`.
374-
return existingAnimation.runner;
375-
}
369+
//we return the same runner since only the option values of this animation will
370+
//be fed into the `existingAnimation`.
371+
return existingAnimation.runner;
376372
}
377373
}
378374
} else {

test/ngAnimate/integrationSpec.js

+38
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,44 @@ describe('ngAnimate integration tests', function() {
351351

352352
dealoc(element);
353353
}));
354+
355+
356+
it("should not normalize classes in a follow-up animation to a joined class-based animation",
357+
inject(function($animate, $animateCss, $rootScope, $document, $rootElement, $$rAF) {
358+
359+
ss.addRule('.hide', 'opacity: 0');
360+
ss.addRule('.hide-add, .hide-remove', 'transition: 1s linear all');
361+
362+
jqLite($document[0].body).append($rootElement);
363+
element = jqLite('<div></div>');
364+
$rootElement.append(element);
365+
366+
// These animations will be joined together
367+
$animate.addClass(element, 'red');
368+
$animate.addClass(element, 'hide');
369+
$rootScope.$digest();
370+
371+
expect(element).toHaveClass('red-add');
372+
expect(element).toHaveClass('hide-add');
373+
374+
// When a digest has passed, but no $rAF has been issued yet, .hide hasn't been added to
375+
// the element, which means class normalization does not allow .hide to get removed
376+
$animate.removeClass(element, 'hide');
377+
$rootScope.$digest();
378+
$$rAF.flush();
379+
380+
expect(element).toHaveClass('hide-remove hide-remove-active');
381+
382+
//End the animation process
383+
browserTrigger(element, 'transitionend',
384+
{ timeStamp: Date.now() + 1000, elapsedTime: 2 });
385+
$animate.flush();
386+
387+
expect(element).not.toHaveClass('hide-add-active red-add-active');
388+
expect(element).toHaveClass('red');
389+
expect(element).not.toHaveClass('hide');
390+
}));
391+
354392
});
355393

356394
describe('JS animations', function() {

0 commit comments

Comments
 (0)