It's normal that AngularJS creates a new ng-view every time a route is loaded, and then destroys the previous ng-view? It's just a fraction of time, but I can see both views on my app, and some directives which gather the element top also notice that behaviour (it seems that compilation is done before the original ng-view is removed from the DOM)
Has someone noticed this behaviour?
Yes, it's normal, this allows you to have transitions when the view gets replaced.
From the official documentation of ngView:
enter - animation is used to bring new content into the browser. leave
- animation is used to animate existing content away.
The enter and leave animation occur concurrently.
Actually ngView is not the only directive that behaves like that, for instance ngRepeat behaves exactly the same.
If you want to make sure that your views don't overlap, you could try this.
Add a class to the element of the ng-view so that you can easily target it from your css, something like this:
<div ng-view class="your-view"></div>
And then in your css do this:
.your-view.ng-leave { display:none; }
Related
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.
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.
I am using UI router in an angular application where basic animations of views using ng-enter(-active) and ng-leave(-active) classes are not enough. I have already used $stateChangeStart event in an app before to scroll up before the statechange but I would like to work with the ui-views even more.
Therefore I tried to find out how the statechange process affects ui-view elements in DOM, but somehow I can't find what I am looking for.
The process I researched fires events in following order: stateChangeStart > viewContentLoading > stateChangeSuccess > viewContentLoaded. Unfortunately when I look at the DOM (using Chome dev console), only during the last breakpoint (viewContentLoaded) there are both ui-views in DOM (the "fromState ui-view" and the "toState ui-view").
I've been thinking of fading the former ui-view element, doing some other stuff and then fading the new ui-view element in so I was looking for an event where only the former ui-view exists, then both and then only the new. This way it seems to me that I should perform all the animations inside the viewContentLoaded callback which seems inappropriate.
Am I missing something in the whole concept or is there another events or approaches to this? Thanks in advance for any hints or links...
My problem is that when I use ng-cloak in pages that include elements which make use of directives with template code, ng-cloak does not wait for this template code to load and the page is shown incrementally and not as a whole (page elements first and after a while template code pops out).
I have tried to make a custom ng-cloak directive so that it won't remove element's ng-cloak class while any child element contains ng-cloak class but with no success. I thought this one would be a common issue, but I have not managed to find a solution online. Any help appreciated!
I don't think ngCloack was designed to cloak your content until everything is loaded. It is designed to prevent your content to be rendered in its raw form, what with expressions and all.
However, according to the documentation, it might work on the body element, but I haven't verified it myself:
The directive can be applied to the <body> element, but the preferred
usage is to apply multiple ngCloak directives to small portions of the
page to permit progressive rendering of the browser view.
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.