ngSwitch and ngIf flicker in Angularjs 1.2.0-rc1 - angularjs

Recently migrated to 1.2.0-rc1 and really happy with it. Especially for the ngIf which can be a big performance improvement for rendering, compared to ngShow.
Except there is some flickering when the boolean changes. See the plunkr below for an example:
http://plnkr.co/edit/iYMm0IHZkrRamlaEs9yD?p=preview
On Chrome (v28), you'll see that the first 2 implementations will flicker whereas the 2 others won't.
On Firefox, the flicker happens only rarely.
Is that normal? Is there a way to avoid that? Should I go back to using ngShow?
Edit:
As sza said, ngIf and ngSwitch modify the DOM, whereas ngShow uses a css rule to display/hide elements. In angular 1.0.7, ngSwitch existed already and was already modifying the DOM and was great as we used it a lot in place of ngShow to avoid expensive rendering of things that were not displayed.
Now if you look at http://plnkr.co/edit/pIpEYZ5K8xvfd9dhAC74?p=preview, you'll see that there is no flickering with ngSwitch from 1.0.7.
The answer I'm expecting would be something like "this is normal behaviour, you're using ngSwitch and ngIf where they shouldn't be used, only static content should be displayed with ngSwitch and ngIf" or "this is a rendering bug, live with it until it is fixed". Of course a workaround would be nice too (#timp, I've seen your answer but I'm afraid I'd need a working example).

I asked the same question on the google group, and the answer was that it is a bug in the animation module:
https://groups.google.com/d/msg/angular/Fy-rVdXh5WQ/aqhppEl8Nw0J
Removing the dependency on the animation module will fix the flicker.

If you look into the source code, you will see both ngIf and ngSwitch are all related to DOM manipulation, while ngShowHide only manipulates the CSS rather than DOM.
I guess the DOM manipulation will be a slightly more expensive than CSS change in terms of reflow and it may differ in different browsers.

If you try the ngIf demo on the AngularJS documentation page (link), it has the same issue you described when the checkbox is toggled quickly.
If the improvement in rendering is important, try replacing the checked with two booleans. This way you can specify the order of which ngIf is evaluated first. It's a pain but it does the job.

Related

Angular ui.scrollpoint prematurely applying ui-scrollpoint class

This has been frustrating me for hours – so time to turn to the good people of SO.
In my angular app I am using ui-scrollpoint to affix a sidenav once it is scrolled to the top of the screen. It is working as intended when using an absolute scrollpoint value (ui-scrollpoint="150") but not when using a relative value (ui-scrollpoint="-100").
The problem at the moment is that the ui-scrollpoint class is applied to the element when the view is loaded (I am using ui-router), even when it shouldn't be.
Even more frustrating is that I haven't been able to recreate the problem in Plunker - here I have mocked the layout of my app - but ui-scrollpoint works as one would expect.
What could be causing this erroneous behaviour? (Documentation is non-existent)
Does the ui-scrollpoint's parents all need to be display: block and
or position: absolute? (Although I've tried this.)
Does it not work in nested states? (The plunker shows that this is
ok.)
Does it not work inside custom and/or transcluded directives. (Again - the plunker shows that this is ok.)
What styling might be on the various parent elements to make this not work?
The only thing I can think is that the class is set permanently somehow when the directive is compiled before rendering / insertion.
When ui-scrollpoint="" or ui-scrollpoint="0", the page renders correctly, but the class gets added as soon as the page is scrolled, even if the element is further down the page.
When ui-scrollpoint="-100", the class is applied from the beginning. It's as if the browser thinks the window has already scrolled past the element.
Help appreciated!
After no luck recreating the issue on Plunker and trying to find the root cause (which wasn't my custom directives and wasn't my layout), I thought to re-download and install the latest scrollpoint.js.
It is now working. Perhaps a bug in an old version. Perhaps I mistakenly edited my local copy.

AngularJS: Expressions visible when IE unloads

I've run into a problem where refreshing an AngularJS page in IE shows the uncompiled AngularJS. I can use ngCloak to hide the uncompiled expressions when loading, but I can't find anything for when the page unloads. I can use ngBind instead of an expression, and then the expressions disappear instead of displaying raw, but I'm hoping for a better solution. Any ideas?
I'm still working on a demo where you can see the issue; I think the iframes used to display results in code snippets and stuff like JSFiddle are preventing me from replicating the problem.
A few tips that may or may not help.
Contrary to common advice, load Angular in head of document. That way when you hit an ng-if during page load, the browser knows what to do with it. If it's in footer ng-if is meaningless until page is loaded and thus elements flash up and then disappear during page load
Use class .ng-cloak as you are doing already.
Use booleans in controller to dictate when to display elements. E.g.
<section ng-if='controller.loading === false'>
you could place some of or your entire markup for a view in such a div to remove elements until they are ready for display
Play with ng-if ng-show and ng-hide, ng-if actually removes elements from the DOM whereas the other two just show or hide. They can produce very different results in terms of smoothness of page loading.
Where you use an expressions on an ng-if, be careful to ensure the expression is very accurate. Don't be sloppy with the expression. Consider what would happen if the var in the expression was undefined. Would your element show when you don't want it to?
Whilst I haven't directly dealt with unloading these same concepts can be applied.

How to disable animations for changes in dataset for ng-repeat in Angular Material?

I'm using Angular Material 1.0.1 library, but I don't want DOM elements' removal to be delayed when using ng-repeat. When the dataset changes, elements stick around for a little bit more and it looks like the page is lagging.
I found out that disabling all animations with $animate.enabled(false) fixes that problem, but still I want some animations, such as for $mdToast to be shown.
How to disable animations only for changes in dataset for ng-repeat?
After doing some research, I think I found my answer.
AngularJS's animations are built to work with CSS transition rules, so I just made the objects disappear with CSS as soon as they were being "animated out".
.repeated .ng-leave {
display: none;
}
This approach works, but still attaches unnecessary animation classes to new objects, which might affect performance. Any suggestions on how to fix this are welcome.
As you already found out, you can use $animate. There is a function that takes the element as argument, so you don't have to disable it globally: $animate.enabled([element], [enabled]);
It should be pretty easy to write a directive which disables the animations on the directive's element.
Alternatively you can probably configure the $animateProvider with $animateProvider.classNameFilter([expression]); to exclude elements with a certain CSS class, the parameter is a RegExp - so something like /^(?:(?!repeated).)*$/ may work (not tested).
If you are after performance then the second approach is probably what you are after. From the docs:
Sets and/or returns the CSS class regular expression that is checked when performing an animation. Upon bootstrap the classNameFilter value is not set at all and will therefore enable $animate to attempt to perform an animation on any element that is triggered. When setting the classNameFilter value, animations will only be performed on elements that successfully match the filter expression. This in turn can boost performance for low-powered devices as well as applications containing a lot of structural operations.

how to prevent AngularJs from having old view and new view on dom when route changes

I am using a directive "slideable" which creates a slideout area and has a toggle. This code that was not written by me but it demonstrates a larger issue for me. When I changing views (most commonly /user/:id type), slideable is a directive used on the template. The directive searches for an element during its link function and binds a click event. The issue is that when I am changing routes and the new view ( same type but different id ) is being loaded the directive is re-binding to the old view. If I stop the browser in chrome during the link then I will see two ng-views on the dom and the issue is it binds to the one that is leaving.
I also have other issues that appear to be related to this phenomenon. Is it normal that the old view would still be on the dom while the new view is being formulated?? Why wouldnt the old-view be destroyed before the new one is rendered? How do I get around this issue in a directive like this?
Thanks.
I am looking to understand conceptually what is happening. I already modified the directive to select the latest view and to appropriately search and bind to the correct element. But I am a bit perplexed as to why there would be a state where both co-exist on the dom.
One definitive reason why the old HTML fragment is briefly present along with the new one is to support animation of transitions from the old to the new. Take a look at the ngView documentation and you'll see an example of an animated transition, and it'll be clear that this is not a bug or a design flaw.
Usually when someone has problems with binding to the right element or element's event, it's because they are selecting the element without limiting the scope of the selector to the HTML fragment being added or updated, or trying to target parts of the DOM outside of the directive. So that's the first place to check, that the directive is doing things right, but like I said we'll need code to check on that.

Angular.js // ng-leave state before url/ng-view change

Getting into ngAnimations; I was wondering how page transition could completely be controlled.
I mean by this : being able to control the same way an ng-leave as it is done for the ng-enter while having a change in the url in the process. New to angular but I'd described it as trying to get some ng-leave control before an ng-view change.
As far as I've searched, the ng-leave state only has a meaning with ng-switch (there is another ng but you got the idea); which for the moment means for me that all the elements have to be already in the page and that no url change are involved in the process.
If any help, highly appreciated. I've found the ng-animations really cool but thinking that this point is quite missing.
Assuming there might be another pattern to follow probably though.
Have you read:
Animation in AngularJS
http://www.yearofmoo.com/2013/04/animation-in-angularjs.html
Enhanced Animation in AngularJS
http://www.yearofmoo.com/2013/05/enhanced-animations-in-angularjs.html
Remastered Animation in AngularJS 1.2
http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html
I have found these useful.

Resources