fix(ngAnimate): run structural animations with cancelled out class changes
When multiple animations on the same element are queued before a $digest passes, the animator tries to create as few actual animations as possible by joining / canceling redundant animations. Class-based animations for example are cancelled when the classes that are added and removed are the same, and the result is no class-change. This however must only happen if there's no structural animation currently queued. Fixes #14249
This commit is contained in:
@@ -82,6 +82,11 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
||||
});
|
||||
|
||||
rules.cancel.push(function(element, newAnimation, currentAnimation) {
|
||||
// cancel the animation if classes added / removed in both animation cancel each other out,
|
||||
// but only if the current animation isn't structural
|
||||
|
||||
if (currentAnimation.structural) return false;
|
||||
|
||||
var nA = newAnimation.addClass;
|
||||
var nR = newAnimation.removeClass;
|
||||
var cA = currentAnimation.addClass;
|
||||
|
||||
@@ -1104,7 +1104,8 @@ describe("animations", function() {
|
||||
$animate.removeClass(element, 'active-class');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(doneHandler).toHaveBeenCalled();
|
||||
// true = rejected
|
||||
expect(doneHandler).toHaveBeenCalledWith(true);
|
||||
}));
|
||||
|
||||
it('should cancel the previously running removeClass animation if a follow-up addClass animation is using the same class value',
|
||||
@@ -1123,7 +1124,8 @@ describe("animations", function() {
|
||||
$animate.addClass(element, 'active-class');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(doneHandler).toHaveBeenCalled();
|
||||
// true = rejected
|
||||
expect(doneHandler).toHaveBeenCalledWith(true);
|
||||
}));
|
||||
|
||||
it('should merge a follow-up animation that does not add classes into the previous animation (pre-digest)',
|
||||
@@ -1198,6 +1200,29 @@ describe("animations", function() {
|
||||
|
||||
expect(capturedAnimation[2].addClass).toBe('blue');
|
||||
}));
|
||||
|
||||
it('should NOT cancel a previously joined addClass+structural animation if a follow-up ' +
|
||||
'removeClass animation is using the same class value (pre-digest)',
|
||||
inject(function($animate, $rootScope) {
|
||||
|
||||
var runner = $animate.enter(element, parent);
|
||||
$animate.addClass(element, 'active-class');
|
||||
|
||||
var doneHandler = jasmine.createSpy('enter done');
|
||||
runner.done(doneHandler);
|
||||
|
||||
expect(doneHandler).not.toHaveBeenCalled();
|
||||
|
||||
$animate.removeClass(element, 'active-class');
|
||||
$rootScope.$digest();
|
||||
|
||||
expect(capturedAnimation[1]).toBe('enter');
|
||||
expect(capturedAnimation[2].addClass).toBe(null);
|
||||
expect(capturedAnimation[2].removeClass).toBe(null);
|
||||
|
||||
expect(doneHandler).not.toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('should merge', function() {
|
||||
|
||||
@@ -756,5 +756,43 @@ describe('ngAnimate integration tests', function() {
|
||||
expect(child.attr('style')).toContain('50px');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should execute the enter animation on a <form> with ngIf that has an ' +
|
||||
'<input type="email" required>', function() {
|
||||
|
||||
var animationSpy = jasmine.createSpy();
|
||||
|
||||
module(function($animateProvider) {
|
||||
$animateProvider.register('.animate-me', function() {
|
||||
return {
|
||||
enter: function(element, done) {
|
||||
animationSpy();
|
||||
done();
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
inject(function($animate, $rootScope, $compile) {
|
||||
|
||||
element = jqLite(
|
||||
'<div>' +
|
||||
'<form class="animate-me" ng-if="show">' +
|
||||
'<input ng-model="myModel" type="email" required />' +
|
||||
'</form>' +
|
||||
'</div>');
|
||||
|
||||
html(element);
|
||||
|
||||
$compile(element)($rootScope);
|
||||
|
||||
$rootScope.show = true;
|
||||
$rootScope.$digest();
|
||||
|
||||
$animate.flush();
|
||||
expect(animationSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user