angular / angular.js

AngularJS - HTML enhanced for web apps!
https://angularjs.org
MIT License
58.82k stars 27.5k forks source link

Angular 1.5.8 - flickering related to ng-show/hide #15461

Closed psmyrdek closed 7 years ago

psmyrdek commented 7 years ago

I've updated my app written in Angular 1.4.1 to Angular 1.5.8 and in some places some weird things started to happen.

Mostly it is about flickering of directives with ng-show / ng-hide used on them. I read here #13974 about similiar issue but I can't fix it with any solution posted there.

You can see the demo here - it's about that red indicators below each input:

out

More info - in these inputs I'm using typeahead directive from AngularUI Bootstrap. Typeahead popup template is being fetched from external file (not inlined).

Narretz commented 7 years ago

Looks similar to https://github.com/angular/angular.js/issues/14015 for which I wrote a pach, but never opened a PR :/

psmyrdek commented 7 years ago

Unfortunately I tried to use patch from this issue you've attached and no difference :/

And all of this looks similar to @garycuthbert comment:

another issue we were seeing with our directives, we use a lot of nested directives that use templateUrl and, with the latest angular release, we started to see some fairly ugly transient rendering on initial page loads & view transitions.

Same here :/

gkalpak commented 7 years ago

I wonder if this is also related to https://github.com/angular/angular.js/issues/15426#issuecomment-263688327. @psmyrdek, does it happen on a specific browser or not? Could you create a live reporduction (e.g. using CodePen, Plnkr etc)?

psmyrdek commented 7 years ago

It has been tested on Chrome, Safari and Firefox - the same problems on every mentioned browser.

@gkalpak your reply from #15426 looks promising (when speaking about solving this issue). I do have some places with ng-show initialized with falsy values (don't ask me why) and before migration to 1.5.8 it was working ok (at least from the user's perspective). Now there's a blink when ng-show="falsy value" turns into ng-hide.

Here's an example with blinking warning (refresh a few times to see it): http://codepen.io/psmyrdek/pen/BQJQed

This issue propagates also to the sections of my app with more complex components / route changes (flickering during initialization of the view).

gkalpak commented 7 years ago

@psmyrdek, your demo shows something different: The flickering is caused by the element being shown before angular takes over and hides it. Issues such as this can be solved with ngClock (and the appropriate styles - if necessary).

Can you try the following directive and see if the flickering goes away in your route changes:

.directive('ngShow', function() {
  return function(scope, elem, attrs) {
    var doShow = scope.$eval(attrs.ngShow);
    elem[doShow ? 'removClass' : 'addClass']('ng-hide');
  };
})
psmyrdek commented 7 years ago

@psmyrdek, your demo shows something different: The flickering is caused by the element being shown before angular takes over and hides it

My question is why places like that worked well in 1.4.1 but now I see flickering.

Of course I agree that places with ng-show="falsy value" are vulnerable to this kind of issues, and I agree that there should be used ng-cloak with "css styles fallback" to prevent these problems, but as I said - in my case it wasn't possible to reproduce this issues in 1.4.1. Is newer Angular slower a bit in terms of initialization, or what?

This is just one of two - the second problem is still related to places with heavier route changes and posted workaround. My friend @jerry23 is also involved in this project and he can say something more about it..

Narretz commented 7 years ago

@psmyrdek I can reproduce the initial flickering in your codepen even in 1.4.1 in Chrome.

gkalpak commented 7 years ago

@psmyrdek, this has nothing to do with being heavier. A bad network for example can have a dramatic impact on how long it takes for the script to load. This can definitely be an issue with older versions. But just to be clear, flickering on elements that are included in your index.html (as in your demo) are totally different than flickering on elements that are included inside templates (such as those related to your routes).

So, it is this second category (flickering inside templates) that we need to investigate and if necessary address. Can you try my directive and report back if route flickering keeps appearing and if it has any unwanted side effects (e.g. in terms of initial animations etc)?

It would also be tremendously useful, if you could put together a minimal reproductionof the flickering (e.g. using CodePen, Plnkr etc).

jerry23 commented 7 years ago

@gkalpak, I tried to use this directive but in some cases, it doesn't work correctly. Now in some places, I'm seeing elements which should be hidden e.g dropdowns list, content messages, error messages in forms. Adding ngCloak in all places where the problem exists will be painful and it can be impossible in some cases (external directive).

gkalpak commented 7 years ago

I tried to use this directive but in some cases, it doesn't work correctly.

Any pattern regarding the "some cases" that it does or doesn't work? We can't really do much without a reproduction or more insight on the exact usecase that is affected by the issue 😞

--

Now in some places, I'm seeing elements which should be hidden e.g dropdowns list, content messages, error messages in forms.

Now, that is weird. If you could share a repro of that, it would be very helpful too. But I understand it is usually difficult to reproduce a corner case in a minimal demo.

--

Adding ngCloak in all places where the problem exists will be painful and it can be impossible in some cases (external directive).

Once again, I only suggest ngClock for elements that appear in the original (static) HTML in your index.html.

psmyrdek commented 7 years ago

Unfortunately, it's so far impossible to reproduce this issue in apps of that scale: http://plnkr.co/edit/DZdAYxk836dDtoGRQgI7?p=preview

That's kind of 1:1 reproduction of situation from GIF from 1st post. We're using typeahead, which contains typeahead-popup directive inside. Template of this directive is being fetched from external file. It also contains that problematic warning element, with ng-show set to falsy value at the beginning. And that's the place where flickering/blinking occurs.

But on plnkr works good so far... It's hard to show anything more. Next step would be to show posts from real life app which is much more complex, but I think that's impossible for now.

Narretz commented 7 years ago

Maybe there's some css / styles that's causing problems? For example, a css transition on an element with show / hide could cause issues.

psmyrdek commented 7 years ago

As we've just noticed, entirely removed ngAnimate restored our app back to normal. What does it mean guys?

Tries with Angular 1.5.8 + angular-animate 1.4.1 failed, tries with angular 1.5.9 with latest animate failed, the same with 1.6.0-rc2.

Of course that's not end for us, we have to handle missing angular-animate now.

gkalpak commented 7 years ago

Unfortunately, it is really hard to tell without a repro. I am also still surprised that the directive above does not work (but it might depend on the implementation of other involved directives). Can you check what happens if you add the ng-hide class (in the HTML) to the problematic elements?

(BTW, is this app publicly available by any chance?)

gkalpak commented 7 years ago

Since we haven't heard back from the OP and most importantly we don't have a reproduction, I am going to close this for now. Similar flickering problems are already tracked in other open issues anyway. (Happy to reopen as soon as there is some reproduction or verification that this is a different/new issue.)

ShankzPatil commented 7 years ago

Working for me.

.directive('ngShow', function() { return function(scope, elem, attrs) { var doShow = scope.$eval(attrs.ngShow); elem[doShow ? 'removeClass' : 'addClass']('ng-hide'); }; })