angular / angular.js

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

ng-hide and ng-show showing at the same time for a short period of time in IE11 #14015

Open PhilipWallin opened 8 years ago

PhilipWallin commented 8 years ago

When including ng-animate there seem to be a brief period of time where a ng-show and ng-hide element are showing at the same time, even if no animations are used.

Example (the problem is only visible if using IE11): http://plnkr.co/edit/vqVGcf9cjFQPAbq0Igyq?p=preview

In the example you can see the flickering of the two elements showing at the same time when checking and unchecking the checkbox which trigger ng-show/ng-hide.

Narretz commented 8 years ago

This sounds familiar. The problem is that I can never reliably reproduce these in IE11. It has happened maybe once in 30 times for me. I've also seen it once on Firefox, so it maybe has something to do with how fast the browser flushed the requestAnimationFrame queue, or with how long we take to detect if animations are allowed.

Narretz commented 8 years ago

Can you please test with the latest snapshot: http://code.angularjs.org/snapshot/angular-animate.js and see if it happens less often?

PhilipWallin commented 8 years ago

In my IE11 I get the flash of both showing every time I click the checkbox. Using the linked angular-animate didn't seem to change this behavior.

Narretz commented 8 years ago

That's weird. What IE and OS version do you have? And is your computer generally slow or under load?

PhilipWallin commented 8 years ago

We have quite high-end computers (I tried on three of them), my initial guess was actually that it was fast enough to show something which is only visible for a short amount of time. I'm running Windows 8.1 with IE version 11.0.9600.18202. One of the computers I tried it on was Windows 7, showing the same problem.

PhilipWallin commented 8 years ago

I'm currently applying this css to avoid the problem: .ng-hide.ng-hide-animate { display: none !important; }

This could of course cause problems for us in the future if we want to animate some ng-hide and not animate some.

Narretz commented 8 years ago

Hm, I didn't think about the computer being too fast. That could it be it. I also have a slightly newer version of IE11 (11.0.9600.18204), but I doubt that this is the reason.

PhilipWallin commented 8 years ago

I tried this now in IE11 on my virtual Windows 7, and experience the problem maybe once every 2-10 try. This could be because my virtual machine is running slower, but this is only a guess.

dgieselaar commented 8 years ago

I'm having the same problem in Chrome, w/ an ng-switch. The specific case where it happens is when a view value change in ngModel is committed, which a) removes a ng-valid-parse class on the parent form, b) removes a class on the form field (a custom empty class) and b) flips an ng-switch (because the form field is then disabled). It happens because the parent animation (a) task runs first, and the scheduler waits until it is completed, then requests another frame to run the task from the form field (b), then waits another frame to run the ng-switch animation task (c), causing a flicker of one frame where both the elements in the ng-switch are temporarily displayed.

dgieselaar commented 8 years ago

image

Narretz commented 8 years ago

@plestik can you post a demo in a plnkr.co or similar?

dgieselaar commented 8 years ago

@Narretz I'll give it a shot. But is this even supposed to work w/ nested animations if it only runs one group of animations every frame?

dgieselaar commented 8 years ago

Sorry, can't reproduce it in a Plunkr.

dgieselaar commented 8 years ago

@Narretz is there anything I can do to help resolve this issue? If you want to, I can provide you w/ login credentials for our staging environment where I can reproduce it consistently.

Edit: I missed the part of the docs where it quite clearly says that combining structural animations w/ class animations can lead to flickering. Never mind me, then.

adamreisnz commented 8 years ago

I am experiencing similar issues on Chrome with OS X. In my case it's two ng-show's with distinct display conditions (which are never true at the same time). Even if I toggle the two conditions immediately after one another, there is a brief moment where both elements are visible. This doesn't happen in all page configurations, but happens pretty consistently in one particular case.

chillyistkult commented 8 years ago

I also have the same issue in Chrome on Windows, using angular and angular-animate 1.4.12.

@PhilipWallin solution is a good workaround for now.

benbabics commented 8 years ago

I'm experiencing the same issue in the iOS Simulator for iOS 9.3. I have uploaded a video demonstrating the issue: https://youtu.be/C0Lh5B1Lj6k

Dhineshin commented 8 years ago

I recently got my hands dirty using Angular material and included in my existing project and started experiencing this flickering behavior in Chrome while using ng-if/ng-show. After some trail and error found the issue caused due to "ngAnimate".

@PhilipWallin solution works as a workaround for me and not sure what would not work in future.

Just added the below in my CSS and replaced my "ng-if" to "ng-show" .ng-hide.ng-hide-animate { display: none !important; }

P.S : using Angular and ngAnimate version v1.5.7

bzitzow commented 8 years ago

+1

garycuthbert commented 8 years ago

Hi, I am experiencing a similar issue with angular 1.5.8 (having just upgraded from v 1.12.15).

The problem is very apparent under IE11, it is there under Chrome also but more often than not the transition is too fast to notice.

The directive i have is a tab control that uses transclusion to include tab pages. The flicker i am experiencing (which briefly shows the new and old active tab page html side by side) is when the user switches between tabs (i.e. after compilation and template loading). The code uses ng-show with a boolean flag to decide whether or not to display the page (of which a maximum of 1 is active at any one time). If i replace ng-show with ng-if there is no flicker.

The work around i had been planning to use was to use ng-class with the same ng-show conditional flag to activate a custom css class '.myCloak { display: none !important}' (i.e. the same css used by ng-cloak) e.g. ng-show="tab.active" ng-class="{'myCloak' : tab.active}" which does work around the problem.

I will attempt to create a plunkr to demonstrate but it may take a while.

In the meantime i will attach a screen shot of the issue as it appears in our app under IE11 and the video it was taken from.

ng-show_issue_01

On the screen shot the area within the thin red rounded rectangles show the tab page that is incorrectly being displayed and the relevant DOM inspection. The blue rounded rectangle areas highlight the active tab which is also shown.

By playing the video [http://take.ms/czZZV] you will see that it is not consistent but it does happen often.

maxnathaniel commented 8 years ago

I have the same issue on chrome 54 with Angular 1.5.8.

@PhilipWallin solution works for now too.

Any idea what the cause could be?

garycuthbert commented 8 years ago

Hello, I have managed to put together a plunk showing this behavior:

[https://plnkr.co/edit/PTrvz8]

If you run it under IE11 and switch between the tab pages you should see it. The code is a little ugly but it shows the problem. If you uncomment the ng-hide-animate override in style.css ( @PhilipWallin work around) the problem goes away.

I will tidy this up on monday and post a video of the problem using the plunk in case you still can't reproduce. Hope this helps...

garycuthbert commented 8 years ago

I have tidied up the plunk a little and added a description, https://plnkr.co/edit/l70kaJ there are blue and red borders around the respective tab pages to make the double rendering move obvious (under IE11)

garycuthbert commented 8 years ago

As @teterovic discovered in issue #13974 this behavior seems to have be introduced in version 1.4.5. If you change the angular and angular-animate versions on the plunk to 1.4.4 the behavior is not there, up it to 1.4.5 and it appears.

Narretz commented 8 years ago

@garycuthbert Thanks for the plnkr, it shows the issue very well (in IE11). I will investigate and see if there's anything we can do. In the meantime, if you don't actually use animations on the elements, you can the classNameFilter to disable animations on that element: https://code.angularjs.org/snapshot/docs/api/ng/provider/$animateProvider#classNameFilter

Narretz commented 8 years ago

Hello everyone, I've created a patch for @garycuthbert's example. Can everyone affected by this issue please test with this angular-animate file and report back if the problem goes away or the behavior is improved? https://rawgit.com/Narretz/angularjs-plunks/master/nganimate-ie-flicker-14015-2/angular-animate-patch-1.5.x.js

garycuthbert commented 8 years ago

Hi, i may be applying the patch incorrectly but i am getting the following error using this file:

angular-animate-patch_console_error

I have tried replacing the content of the previous angular-animate.js file as well as explicitly loading the angular-animate-patch.js file, complaining about 'unknown provider '$$isDocumentHiddenProvider''. I am running against the 1.5.8 release, am i missing something?

Narretz commented 8 years ago

Hi @garycuthbert I originally had linked the patched file for angular master. Here's the one for the 1.5 branch: https://rawgit.com/Narretz/angularjs-plunks/master/nganimate-ie-flicker-14015-2/angular-animate-patch-1.5.x.js

garycuthbert commented 8 years ago

Thanks @Narretz, I have tried your patch and it resolves the issue for me under IE11, is this fix likely to make it into the next 1.5 release?

Narretz commented 8 years ago

I'll wait a few days for someone else to test, but otherwise I will merge it next week. We currently have no release date for 1.5.9, so I think it'll make it into it. I just can't say when 1.5.9 will be released ...

garycuthbert commented 8 years ago

Great, thanks for the fix @Narretz I will keep an eye out for the next release.

I can't be sure yet but i think this fix may also help 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.

Although I appreciate (more so now) that the templateUrl mechanism is asynchronous and parent/child directives cannot wait on each others to load the kind of transient rendering we were seeing looked similar to this issue i.e. mutually exclusive chunks of dom being rendered briefly in the same space. We are managing to ease the issue by using 'template' instead of 'templateUrl' and returning the html from a template cache to speed up the load but I will undo some of these changes and retest with your animate patch to see if it helps.

garycuthbert commented 8 years ago

As a final observation i think there are similar problems with the ng-include and ui-view animation hooks. It is very difficult to pin down but as our app uses both directives extensively the net effect is quite noticeable under IE and to a lesser extent under Chrome (the effect is the brief rendering of mutually exclusive chunks of dom i.e. the same issue @Narretz has addressed for ng-hide above). I had been able to improve the situation by pre-loading our custom directive templates and using 'template' to access them and by reacting to the load/loaded events fired by ng-include and ui-view (using a custom class 'display : none !important' to cloak the relevant nodes between the load and loaded events) but the problem was still occasionally seen.

Having undone all of this and by specifying an exclusion class by setting $animateProvider.classNameFilter as @Narretz suggested the problems disappear.

We do not currently use any animations but this is likely to change in the near future, we can work with the classNameFilter to activate the areas we need though.

@Narretz, not sure if your fix can be applied more generally to cover ng-include & ui-view scenarios but the symptoms certainly look the same.

Narretz commented 8 years ago

The fix is "general" in a sense that it's not in the ngShow/ngHide directive code, but in the animation logic itself. However, ngShow/Hide use a specific animation function (a temporary class), which is not used by ngInclude and ngView. It's hard to say what the problem is with them without seeing an example.

fashaikh2021 commented 7 years ago

Hi Narretz, I have been trying to fix this issue from a while and found this patch here which after applied have fixed the problem for the version 1.5.0.Beta something, but still not working with 1.5.8. Thanks for the path :)

Also in the patch I noticed at once double equal '==' has been used where after changing it to '===' it works. Which is correct syntax for condition check.

I also have tried this in further version 1.5.9 and 1.6.0, it's not still working with patch anyway. Any help will be highly appreciable.

Thanks Fahad

Narretz commented 7 years ago

I will review @gkalpak's PR after Christmas, and then we can hopefully get it in quickly.

fashaikh2021 commented 7 years ago

Tried in further versions not working in 1.5.9 and 1.6.1. Any help / suggestion will be highly appreciable. Thanks Fahad

mmomeni commented 7 years ago

Still the same issue with 1.5.10

stijn26 commented 7 years ago

Had the same issue, wanted to try to upgrade to 1.6.1 from 1.3.x and had to downgrade again to 1.4.4. What an embarrasment for the Angular team

ghost commented 7 years ago

@stijn26 you did probably something wrong and this should be an stackoverflow question but anyway:

stijn26 commented 7 years ago

I checked all breaking changes and modified them, all modules were updated. I had the exact same issue as the rest of the persons in this thread.

fashaikh2021 commented 7 years ago

@mmomeni @stijn26 @teterovic For now, we found the work around which is to turn on and off the animate & it's working fine for us so far. example is below. Hope it may help you guys too until team find the right fix ???

$animate.enabled(false);
    $scope.$on('$destroy',
        function() {
            $animate.enabled(true);
        });
samal-rasmussen commented 7 years ago

I'm getting this flicker with ng-show on angular 1.6.3 on Chrome 57 on Windows 7. The display: none on .ng-hide.ng-hide-animate fixes it for me.

Narretz commented 7 years ago

@samal84 can you please provide a demo? I cannot reproduce this in Chrome 58 with the plnkr in the first post updated to 1.6.4.

samal-rasmussen commented 7 years ago

Ok it looks more like a bug with angular material md-switch, now that I tried to make a minimal demo: http://plnkr.co/edit/hR2B8yEPjak0v2Yryid1?p=preview

Try clicking the switch quickly, and you should see that on/off inside and outside the md-switch behave differently. The one inside flickers with both being rendered for a split second, while the one outside is fine.

vbraun commented 7 years ago

@samal84 That is also fixed by disabling $animate (which angular-material uses). Demo: http://plnkr.co/edit/C08HPffIBTomH1QoBdRD?p=preview