Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

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

Open
topherfangio opened this issue Sep 28, 2015 · 26 comments
Open

Comments

@topherfangio
Copy link

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.

@ThomasBurleson
Copy link

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

@robertmesserle
Copy link

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

@matsko
Copy link
Contributor

matsko commented Sep 29, 2015

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

@topherfangio
Copy link
Author

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!

@Narretz Narretz modified the milestones: 1.4.7, 1.4.8 Oct 1, 2015
@kvetis
Copy link

kvetis commented Oct 2, 2015

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.)

@topherfangio
Copy link
Author

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

@matsko
Copy link
Contributor

matsko commented Oct 5, 2015

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

@Cornally
Copy link

Cornally commented Oct 6, 2015

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!

@codeaid
Copy link

codeaid commented Oct 16, 2015

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.

@klmdb
Copy link

klmdb commented Oct 30, 2015

Having the same issue here.

Chrome 43.0.x
Angular 1.4.7

@Narretz
Copy link
Contributor

Narretz commented Nov 24, 2015

This is the culprit: ea8016c So yeah, it's not an easy fix.

@Narretz
Copy link
Contributor

Narretz commented Nov 30, 2015

@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?

topherfangio added a commit to angular/material that referenced this issue Dec 1, 2015
WIP BRANCH - Not ready for merge.

When the ngMessages directive was used with the ngShow
directive inside of an md-input-container, the UI would
jump rather than properly animating.

Additionally, if the messages spanned multiple lines,
the animations were incorrect due to hard-coded values.

Fix many styles and move animations into JS so we can
properly calculate message heights.

_NOTE: The messages may still jump due to
angular/angular.js#12969; this
fixes a different, but similar bug._
@topherfangio
Copy link
Author

@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
Copy link
Author

@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
Copy link
Author

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!

@Narretz
Copy link
Contributor

Narretz commented Dec 14, 2015

@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: #12969 (comment)

@topherfangio
Copy link
Author

@Narretz Ah, indeed! Apologies for the confusion!

@gkalpak
Copy link
Member

gkalpak commented Dec 15, 2015

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).

@bathos
Copy link

bathos commented Feb 14, 2016

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.

@Narretz
Copy link
Contributor

Narretz commented Feb 15, 2016

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 Narretz modified the milestones: 1.4.x, 1.5.1 Feb 15, 2016
@Narretz
Copy link
Contributor

Narretz commented Feb 15, 2016

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 Narretz modified the milestones: Backlog, 1.4.x Feb 15, 2016
@jaszczakBartosz
Copy link

jaszczakBartosz commented Jul 19, 2016

This worked for me:

.ng-enter-prepare
  display: none

@topherfangio
Copy link
Author

@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?

@C-E-Rios
Copy link

C-E-Rios commented Dec 7, 2016

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

@gkalpak
Copy link
Member

gkalpak commented Dec 7, 2016

@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.)

@C-E-Rios
Copy link

C-E-Rios commented Dec 7, 2016

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests