angular.js icon indicating copy to clipboard operation
angular.js copied to clipboard

ngMessages(ngAnimate 1.4.5?): Flash of content before animation begins.

Open topherfangio opened this issue 10 years ago • 26 comments

I just noticed a bug which I thought was in Angular Material, but I now believe is in Angular itself.

When the animation for my ng-messages begins, there is a flash where you can see all messages before the animation begins. Although the issue is appearing with ngMessages, I think it might be a broader $animate issue because I can reproduce this by upgrading only angular.js and angular-animate.js from 1.4.4 to 1.4.5 (leaving everything else including angular-messages.js at 1.4.4).

Oddly, if I leave either file at 1.4.4 (it doesn't matter which one), the issue is not reproducible, so it seems to be an issue when both files are at version 1.4.5.

Version Introduced: 1.4.5? Versions Tested: 1.4.4 (works here; broken on others), 1.4.5, 1.4.6, 1.5.0-beta.0 Browsers: All (IE Edge, Safari, Chrome/Firefox on both OS X and Windows)

Steps to Reproduce:

  1. Open https://codepen.io/topherfangio/pen/PPbLaR
  2. Click on the input and type a 5 so the new value is 12345

You will see the errors appear for a split second, disappear, and then they will animate into place.

Again, you can edit the Codepen settings to change either file to 1.4.4 and it fixes the issue.

Additional Info:

Might be related to #12825.

I did not see any relevant breaking changes in the changelog between 1.4.4 and 1.4.6 which would account for this. Please let me know if I can provide any additional information.

topherfangio avatar Sep 28 '15 22:09 topherfangio

@robertmesserle - is this related to any changes you may have made ? @matsko - what are your thoughts here ?

ThomasBurleson avatar Sep 29 '15 00:09 ThomasBurleson

@ThomasBurleson If this is an AngularJS issue, then no - I have no commits in the angular.js repo.

robertmesserle avatar Sep 29 '15 02:09 robertmesserle

I see what's going on here. I'll have a look later today.

matsko avatar Sep 29 '15 17:09 matsko

I reproduced the demo without material just to make sure it wasn't some weird interaction with our CSS/JS. You can view it below if it's helpful:

https://codepen.io/topherfangio/pen/zvoXjz

@matsko Thanks for taking a look!

topherfangio avatar Sep 29 '15 18:09 topherfangio

It also happens on ngIf in IE and Firefox, but not in Chrome. I've created a JSFiddle that illustrates the difference:

Reproduction In this fiddle, delete the contents of the input box. http://jsfiddle.net/kvetis/ssnkqog6/3/ Affected Versions: 1.4.5, 1.4.6, 1.4.7 (1.4.4 is okay, probably introduced in 1.4.5) Browsers: Chrome 45 (ngMessages), IE11 (ngMessages, ngIf), FF 39 (ngMessages, ngIf) @ Windows 8.1 home

Interesting thing is that if you try the second form on this Angular Material demo page: https://material.angularjs.org/0.11.2/#/demo/material.components.input The issue does not occur on the Client Name input, but appears on Client Email (I have no theory why.)

kvetis avatar Oct 02 '15 11:10 kvetis

@kvetis The Client Name input does indeed seem to work in Chrome, but it looks like it has the same issue on Firefox/Safari.

topherfangio avatar Oct 02 '15 15:10 topherfangio

I looked into it and it's definitely a bug with ngAnimate. I am currently thinking of a solid solution for it.

matsko avatar Oct 05 '15 18:10 matsko

I was previously animating visibility of adjacent elements using "ngIf" and in some cases "ngShow". Flipping over to "ngSwitch" resolved the flickering issue in 1.4.5+ (everything worked fine in 1.4.4). "ngSwitch" executes at priority level 1200 while "ngIf" is 600. Hope this helps!

Cornally avatar Oct 06 '15 19:10 Cornally

I can confirm that the same is happening to me in Chrome 45 and Opera 32 on Ubuntu 14.04. I can't remember if I had this flickering issue on Windows (been stuck in Ubuntu for too long) but I know for sure that it didn't flicker in the latest Opera on Windows.

codeaid avatar Oct 16 '15 19:10 codeaid

Having the same issue here.

Chrome 43.0.x Angular 1.4.7

klmdb avatar Oct 30 '15 07:10 klmdb

This is the culprit: https://github.com/angular/angular.js/commit/ea8016c So yeah, it's not an easy fix.

Narretz avatar Nov 24 '15 15:11 Narretz

@matsko came up with a workaround for this problem. ngAnimate will provide a new class on the element that is added as soon as a enter / leave / move animation is initialized, and removed before the animation actually starts. That means you can apply styles to the element to make sure it is not visible / there is no flicker. See here: https://codepen.io/anon/pen/NGQXOY

Would that work for you? Or did you find another workaround?

Narretz avatar Nov 30 '15 12:11 Narretz

@Narretz I wound up having to rewrite all of the animations in JS. Since I am manually handling them now, the flicker is gone.

I talked with matsko yesterday and told him I would try to test it on something else later this week.

Thanks!

topherfangio avatar Dec 03 '15 16:12 topherfangio

@Narretz @matsko I have been able to work around the issue in a way by making the default starting state of the elements be hidden and making my animations show them. However, this has some issues because there are cases (again with users using ng-if/ng-show/ng-hide) where my animations don't fire, and since the default state is hidden, things aren't appearing when they should.

I think the ng-enter-prepare class will fix the issue for us, but I have not tested it yet. I will try to do that today.

Is this something that will be back-ported to the 1.3.x series? We need to support both.

topherfangio avatar Dec 09 '15 17:12 topherfangio

Quick update, we have a workaround for some of our default inputs because we auto-hide the messages. However, if someone needs more customization (using ng-if or ng-hide, etc) the messages will still flicker, so it looks like this fix will be necessary.

I still haven't had a chance to test it within our code, but I am pretty confident that the proposed fix will work. Just need to know if it will be available in 1.3?

Thanks so much guys!

topherfangio avatar Dec 14 '15 20:12 topherfangio

@topherfangio I didn't even know this was an issue in 1.3, I thought it happened since the refactoring in 1.4. It doesn't seem to happen with 1.3 in this bin: https://github.com/angular/angular.js/issues/12969#issuecomment-144154302

Narretz avatar Dec 14 '15 21:12 Narretz

@Narretz Ah, indeed! Apologies for the confusion!

topherfangio avatar Dec 14 '15 22:12 topherfangio

I haven't looked into this issue, but I wonder if this is similar to #12825 (i.e. some structural and non-structural animation getting merged).

gkalpak avatar Dec 15 '15 12:12 gkalpak

I encountered this, too. The exit animation is fine, but before the enter animation runs, all ng-messages momentarily display (tested Chrome, FF). Reading through the comments so far, is it correct that there is no known way around this if you're in 1.4.x, except to animate manually?

ng-message {
    display: block;
    margin: 1rem 0;
    transition: max-height linear $fast;

    &.ng-enter {
        max-height: 0;
        overflow: hidden;

        &.ng-enter-active {
            max-height: 2.5rem;
        }
    }

    &.ng-leave {
        max-height: 2.5rem;
        overflow: hidden;

        &.ng-leave-active {
            max-height: 0;
        }
    }
}

Edit: in my case, I was able to solve it in cases where there is only going to ever be one ng-message by adding this:

.ng-inactive > ng-message:not(.ng-leave) {
    display: none;
}

This does successfully keep the message unshown during the would-be flicker. However you need the :not(.ng-leave) there or else it will also dump your exit animation. Unfortunately I don't think this will help except in cases like mine, where there's only ever one ng-message at a time.

bathos avatar Feb 14 '16 14:02 bathos

We've decided to backport the ng-[event]-prepare class back to 1.4.x, and it will be available in the upcoming 1.4.10

Narretz avatar Feb 15 '16 21:02 Narretz

I'm not sure if we can ever provide a "real" fix, since the animation spacing is so essential to ngAnimate now. Moving to the backlog for now.

Narretz avatar Feb 15 '16 21:02 Narretz

This worked for me:

.ng-enter-prepare
  display: none

jaszczakBartosz avatar Jul 19 '16 12:07 jaszczakBartosz

@Unasbj Indeed; this new class was added in more recent versions and allows you to work around this bug.

@Narretz I think this can be closed now?

topherfangio avatar Jul 19 '16 19:07 topherfangio

This is still an issue for me. I've tried some of the workarounds suggested but none work. Maybe I'm missing something?

https://plnkr.co/edit/XYq1wF7la97dIz9Ec33J?p=preview

C-E-Rios avatar Dec 07 '16 14:12 C-E-Rios

@C-E-Rios, you could replace ngShow with ngIf on the [ng-message] elements (and don't need any -prepare styles). (But from a quick look, yours is a different issue than what is being discussed here.)

gkalpak avatar Dec 07 '16 21:12 gkalpak

@gkalpak - Awesome that does the trick. Thank you.

C-E-Rios avatar Dec 07 '16 21:12 C-E-Rios