-
Notifications
You must be signed in to change notification settings - Fork 27.5k
ng-show/hide is delayed on an element that is animating #8224
Comments
ngAnimate is greedy since it assumes that all keyframes/transition code that is active on the element during any of the triggers are there to be animated via ngAnimate. Therefore, in this case, despite To get around this, simple erase the animation styling when the This is a problem with CSS inheritance. If there was a better way to detect styles without having to solely rely on getComputedStyle then these kinds of quirks could possibly be avoided. |
@matsko I think this special case is actually a regression. As you can see in @SimpleAsCouldBe 's plunker, or in this plunker http://plnkr.co/edit/5cfIXfNryNOzK66q9YWL?p=preview, in 1.2.17, the element does not disappear immediately, but in 1.2.16, it does. This is most likely because of 55b2f0e |
Thanks for the workaround, it does the trick as expected. Two points. One is specific to ng-show and one is general. ng-show + infinite animations:Should an infinite animation really delay an PhilisophicalAs a non-contributor I don't have much say, but maybe opt-out isn't the right strategy for this library. It's just so astoundingly magical to have a JS library react to CSS rules.. If I had to tag elements with |
@SimpleAsCouldBe yes I've been thinking the same that maybe it might be best to require all animations to have a Regarding the delay, it's not that there is a delay, it's that ngAnimate cancels out the infinite portion and only runs the animation once. Therefore, when you hide it, it waits for 2s * 1.5 = 3 seconds and then it runs the timeout check and closes of the animation. So it's an unnecessary window of time that shouldn't be there at all--only CSS style detection is highly limited. |
@Narretz while the commit you provided may effect this particular example, it doesn't actually have anything to do with the regression. The reason for this is because the Have a look at the demo below. See how there are two sets of selectors for the It might be best to make ngAnimate less naive and only animate when |
I think if you're open to a breaking change like opt-in animation handling, it would create a less surprising developer experience. Would you be open to prefixing with something angular specific like |
I have the same Problem: |
@tole42 This is the workaround:
|
Thanks for your help. The workaround is not working :( |
@tole42 Nothing in that fiddle animates, as far as I can see. Is the animation part of the Foundation library? A more direct re-creation case would make this easier to debug. Doesn't look like the same issue to me. |
I believe I see the same issue as @tole42 . With ngAnimate include in a module, the standard ng-hide/ng-show functionality doesn't work correctly for the base case when you are not trying to animate them. In other words, when you use ng-hide/ng-show on a plain element with no animation class applied.
If I wanted an animation on that hide, I would do something like:
There are some instances in an app where you may want to animate a show/hide and other instances where you don't want to animate. In the instances where you don't want to animate, you don't decorate the element being shown/hidden with any custom animation class. In this instance, Angular just adds the "ng-hide" class to a hidden element. If you don't include ngAnimate in your module at all, this works as expected: the element disappears immediately. But by simply including ngAnimate, you get the behavior shown in the two fiddles that @tole42 posted: there is a delay before the element that got the "ng-hide" class added actually disappears. It should disappear immediately if you are not trying to use animations on it. A couple of work-arounds that seem to work are:
Or:
But it doesn't seem correct that those should be necessary in the case where you are simply trying to hide something in a non-animated manner. |
Just to follow up on some additional discoveries... Trying to boil down the problem to the simplest possible scenario - showing/hiding plain divs - the problem does not manifest. I noticed in the fiddles posted by @tole42 that the foundation.css was being used, and the example does show the problem with showing/hiding input fields. My experience was similar (seeing the problem manifest with input fields), but using bootstrap.css. Digging into both of those css files more closely, they both apply css transitions to input fields. Those css transitions appear to be the real culprit, as angular-animate is picking up the durations from them. That is what causes the visual delay when showing/hiding those elements, even if you are not intentionally trying to animate that transition. So I don't think this is necessarily a problem that Angular should attempt to solve. It's more of a side-effect of using angular-animate with other css libraries, which may have some embedded css transitions that you are not expecting! Took a long time to track down the root cause, but it was good to finally find a reason that makes sense. |
Yes this is an important issue with ngAnimate, but due to the lack of control of getComputedStyle and the cascade of transitions in other libraries, ngAnimate is unable to detect this. There are two solutions to fixing this:
The reason why it didn't work for you before was because of the lack of CSS specificity.
|
Oh, putting the config in a provider is a nice way to go, I like that a lot, @matsko! |
@pnutshellmenace thanks for the quick solution. It saved my day. |
I don't understand what the final solution here was. @matsko stated:
But I don't see any implementation like that. I took a look at I see no reason why ngAnimate should assume I want to animate everything. There will always be things I don't want to animate, and currently I have more that I do not want to animate than the other way around, which makes manually styling them to disable transitions unappealing. Edit: Found this blog entry that puts things into perspective... I'm going to give it a try: http://blog.fgribreau.com/2014/03/how-to-configure-ng-animate-to-work-on.html Edit 2: Adding I had included a .js file of a third-party angular module that had a dependency on ngAnimate, and somehow that was causing animations to be triggered even on my own module. Somehow ngAnimate was affecting the parent module scope? |
* Other components, like `md-toolbar` use a custom transition on the background-color, color etc, but the related CSS selector has a high specificity. * So for example, when ng-hide is applied, then we set the transition to `none`. But that's not working sometimes, because the both selectors have the same specificity. To fix this, we can apply `!important` or increase the selector specificity by using a CSS hack. https://www.w3.org/TR/CSS2/cascade.html#specificity The toolbar selector has in our case a specificity of 20. * .md-button.ng-hide // 0,0,2,0 * .md-toolbar-tools .md-button // 0,0,2,0 ------ So this is actually a thing, which is caused by $ngAnimate, which is not able to solve this issue. We need to reset the transition duration, when $ngAnimate looks for it, manually. $ngAnimate Issue: angular/angular.js#8224 (comment) Fixes angular#7929
* Other components, like `md-toolbar` use a custom transition on the background-color, color etc, but the related CSS selector has a high specificity. * So for example, when ng-hide is applied, then we set the transition to `none`. But that's not working sometimes, because the both selectors have the same specificity. To fix this, we can apply `!important` or increase the selector specificity by using a CSS hack. https://www.w3.org/TR/CSS2/cascade.html#specificity The toolbar selector has in our case a specificity of 20. * .md-button.ng-hide // 0,0,2,0 * .md-toolbar-tools .md-button // 0,0,2,0 ------ So this is actually a thing, which is caused by $ngAnimate, which is not able to solve this issue. We need to reset the transition duration, when $ngAnimate looks for it, manually. $ngAnimate Issue: angular/angular.js#8224 (comment) Fixes #7929 Closes #8190
I would prefer this answer using |
This is not expected behavior if you're doing a constant animation on something like a loading spinner and just want to hide or show it immediately.
The element was not told to be managed by ng-animate, I just want normal ng-show/hide to happen instantly, and any css animations that happen to be ongoing should be irrelevant, I think.
Fiddle: http://jsfiddle.net/PvS8k/2/
Uncheck "show loader" and note that it takes a few seconds to actually go away.
I think this is a recent change because our loader wasn't sticking in our application before upgrading. I think we were on 1.12 before.
I must be missing something in my understanding of how to use/not use ng-animate, right? In this case I actually want to NOT use it, but if I can use it to ignore this element, that would work too. Definitely surprising behavior though.
The text was updated successfully, but these errors were encountered: