-
Notifications
You must be signed in to change notification settings - Fork 27.5k
fix(ngAnimate): remove event prepare class when skipping animation #16677
Conversation
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed (or fixed any issues), please reply here (e.g. What to do if you already signed the CLAIndividual signers
Corporate signers
|
Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please visit https://cla.developers.google.com/ to sign. Once you've signed (or fixed any issues), please reply here (e.g. What to do if you already signed the CLAIndividual signers
Corporate signers
|
CLA signed. |
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
1 similar comment
We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google. |
51cb9a7
to
feb01ef
Compare
CLAs look good, thanks! |
1 similar comment
CLAs look good, thanks! |
feb01ef
to
5a022bf
Compare
…imation has no duration Background: ngAnimate writes helper classes to DOM elements to see if animations are defined on them. If many elements have the same definition, and the same parent, we can cache the definition and skip the application of the helper classes altogether. This helps particularly with large ngRepeat collections. Closes #14165 Closes #14166 Closes #16613
Thanks for the PR! This looks good at first glance. However, we also need a test for this behavior. Writing tests for ngAnimate isn't the easiest thing, unfortunately. But if you want to give it a shot, here are some tests regarding preparation. angular.js/test/ngAnimate/integrationSpec.js Lines 365 to 469 in a553735
It'll also help if you can tell me how exactly the animation is skipped in your case. |
5a022bf
to
0761de2
Compare
@@ -187,7 +187,7 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro | |||
var element = animationEntry.from ? animationEntry.from.element : animationEntry.element; | |||
var extraClasses = options.addClass; | |||
extraClasses = (extraClasses ? (extraClasses + ' ') : '') + NG_ANIMATE_CLASSNAME; | |||
var cacheKey = $$animateCache.cacheKey(node, event, extraClasses, options.removeClass); | |||
var cacheKey = $$animateCache.cacheKey(node, animationEntry.event, extraClasses, options.removeClass); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still unable to isolate the steps which lead to the issue. While trying to find out I managed to get why it leaves on the containsCachedAnimationWithoutDuration() check. I can see that there is a leave and an enter animation getting triggered. Both are in the animation queue, but when code goes through the animations it creates the cache key based on the first event (leave in this case). When it later comes to the actual execution of the animation it first handles the leave, containsCachedAnimationWithoutDuration() returns false as this key is not in the cache yet and then adds it to cache later (with !valid as the transition-duration is null). Then later the same happens for the enter animation, but due to the same cache key as the leave animation containsCachedAnimationWithoutDuration() now finds the existing non valid entry and returns true and the enter is skipped.
Any idea how the duration can be null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I managed now to reproduce it
http://plnkr.co/edit/6CsoTul8LBIGBcHfioYJ
(hitting action, when text goes red it means we are into the situation).
So you need a directive and changing ng-switch and changing ng-class as far as I see. No idea how to put that into a test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I'll take a look. I take it the custom directive is necessary? replace: true always complicates things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance that one can trigger the animation events for an element in the tests? Might be simpler than rebuilding the complex structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's animationSpec.js, which tests this behavior somewhat in isolation:
angular.js/test/ngAnimate/animationSpec.js
Lines 551 to 571 in a553735
they('should remove the preparation class before the $prop-animation starts', | |
['enter', 'leave', 'move'], function(animationType) { | |
inject(function($$animation, $rootScope, $$rAF) { | |
var expectedClassName = 'ng-' + animationType + '-prepare'; | |
var child = jqLite('<div></div>'); | |
element.append(child); | |
$$animation(element, animationType); | |
$$animation(child, animationType); | |
$rootScope.$digest(); | |
expect(element).not.toHaveClass(expectedClassName); | |
expect(child).toHaveClass(expectedClassName); | |
$$rAF.flush(); | |
expect(element).not.toHaveClass(expectedClassName); | |
expect(child).not.toHaveClass(expectedClassName); | |
}); | |
}); |
But since the cacheKey is created in animateCss, I'm not sure it's possible to recreate the case here.
Maybe we'll have to build a full integration test including the custom directive first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I managed to trim down your plnkr to what I think is the minimum to reproduce the problem: http://plnkr.co/edit/m5CaegjmdtpR1pUX7zZ8?p=preview I'll try to put this into a test, then it should be easier to see what happens when. Interestingly, the ngClass directive is necessary for the bug to appear.
Any idea how the duration can be null?
ngAnimate is reading possible animation styles from the element during animation. So if you have an element / directive that could technically be animated, it will look on the classes to find animations. If none are found (basically the default), the animation duration is null. Or did you mean null as in null and not 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've opened a PR #16681 that simplifies the fix and adds tests
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix
What is the current behavior? (You can also link to an open issue here)
It can happen that an element keeps the ng-enter-prepare css class (maybe for other events as well) when animation is skipped. This can result for example in unwanted invisible elements in your DOM in case prepare phase is using display:none or opacity:0 to avoid blink during animation.
What is the new behavior (if this is a feature change)?
Prepare class is removed when skipping animation.
Does this PR introduce a breaking change?
No.
Please check if the PR fulfills these requirements
Other information: