<html ng-app>
<body>
<p ng-cloak>{{foo}}</p>
</body>
</html>
The way I understand it:
The HTML page is rendered.
DOMContentLoaded is emitted, and Angular starts its bootstrap process.
During the compile phase, when it sees the ng-cloak directive, it applies display: none !important.
During/after the link phase and before the re-rendering, it removes that display: none !important rule from things with the ng-cloak directive.
So I understand why things wouldn't be shown from the time the compile phase starts to the end of the link phase. But I don't understand why things wouldn't be shown from the time the HTML is loaded to the start of the compile phase.
It's all explained in the documentation:
[...] When this css rule is loaded by the browser, all html elements (including their children) that are tagged with the ngCloak directive are hidden. When Angular encounters this directive during the compilation of the template it deletes the ngCloak element attribute, making the compiled element visible.
Other than the explanation in the docs. I've worked on websites that use async calls to retrieve data and I've used ng-cloak to avoid showing variables that might not have a value yet until the end of the compile process. My use case is when the DOMContent might have finished loading way before the compile process ends but my Angular data is not ready yet. Hope this gives you an idea of a use case but that's not the only one.
Related
I have a view containing two nested directives. The inner-directive depends upon the outer-directive to be present. When I load the page from scratch the directives are loaded as expected i.e the outer exists before the inner. But when I navigate from the page and then return, the order of directive-loading is reversed i.e the inner-directive is loaded before the outer-directive. Both directives are costume directives. When I change the outer-directive to instead being a ng-controller, the problem is solved. To perform the navigation ui-router is used. Does anybody know how to solve this issue without having to use a ng-controller as the outer-directive? And why ng-controller solves the problem?
<div outer-directive>
<inner-directive></inner-directive>
</div>
Without knowing a ton about your specific directives, you can take a look a this blog post about directive priority.
(Controller gets processed in a different cycle than directives, so it makes sense that putting whatever 'dependent' code inner-directive requires into a controller solves your problem).
Here's the interesting part: Angular will follow, it appears, this "path" for your nested directives:
outer-directive: compile
inner-directive: compile
outer-directive: pre-link
inner-directive: pre-link
inner-directive: post-link
outer-directive: post-link
The linked blog post explains "why," but this processing order explains your discrepancy between initial page load (where compile is run for the directive) and your page-back case (where the directive is already compiled and we just need to link).
Again, without knowing much about your directives, maybe you need to relocate the dependent outer-directive code into pre-link (instead of link) so that it gets processed first?
You do that by breaking up your Link object into:
Link: {
pre: function(){
},
post: function() {
}
}
Still need help, [here's a decent post] (http://www.undefinednull.com/2014/07/07/practical-guide-to-prelink-postlink-and-controller-methods-of-angular-directives/) on the breaking up link into pre/post.
I have a few bits of HTML like
<p class="noresults">{{numberOfContacts}} Results Are Available</p>
Is it possible for me to hide {{numberOfContacts}} until Angular has loaded? So it would just say Results Are Available
I've seem some solutions such as hiding the entire body until Angular has loaded, but I'd rather not do that if possible.
Yes, use ng-cloak. Simply add class="ng-cloak" or ng-cloak to an element like this
Using directive <div ng-cloak></div>
Using class <div class="ng-cloak"></div>
It's simply a set of CSS rules with display: none !important and as Angular has rendered your DOM it removes the ng-cloak so an element is visible.
use <span ng-bind="numberOfContacts" /> instead of {{numberOfContacts}}
Sometimes, even if I used the ng-cloak, I could still see the braces for a few seconds. Adding the following style resolved my issue:
[ng-cloak]
{
display: none !important;
}
Please see this link link for more explanation.
Hope it helps :D
This is typically only an issue when working with complex content on really slow devices. In those instances, there can be a brief moment when the browser displays the HTML in the document while AngularJS is parsing the HTML, getting ready, and processing the directives. In this interval of time, any inline template expressions you have defined will be visible to the user. Most devices nowadays have pretty good browsers which are quick enough to prevent this from being an issue. There are two ways to solve the problem.
Avoid using inline template expressions and stick with ng-bind directive.
(Best) Use the ng-cloak directive which will hide the content until Angular has finished processing it. Basically, the ng-cloak directive uses CSS to hide the elements and angular removes the CSS class when the content has been processed, ensuring that the user never sees the {{ and }} characters of a template expression.
One strategy to consider is using the ng-cloak directly to the body element, which will ensure that the user will see an empty browser while AngularJS loads. However, you can be more specific by applying it to parts of the document where there are inline expressions.
I have seen issues with ng-cloak not working when added to an element. In the past, I have worked around this issue by simply adding ng-cloak class to element.
You can use ng-bind instead of expression like
<span ng-bind="data"></span>
I'm building a directive that utilizes an ng-if inside of it's template. What's strange is that the element provided to the link function does not have the ng-if code expanded, it is only a comment line for the ng-if. Playing around, I found that by wrapping my link code in a $timeout seems to get it to work, but I am wondering if that is not the correct way of going about it....and more so, why is this happening.
I've added a plunk to demonstrate: http://plnkr.co/edit/Gl7v8yJLevi664nUKcFY?p=preview
Most directives actually do most of their logic in a $watch(). For example ng-if will setup a watch on it's attribute, and then render/remove the dom when that changes. Watches execute during a digest cycle, so even though directives have been compiled and linked, the watch hasn't run yet to determine whether it should show the if or not.
EDIT:
You should probably think about what you are actually doing to make sure if it's what you want. Keep in mind that the ng-if is dynamic. And so at any time it might get removed or added based on whether the items array is empty or not.
This means that even if you manage to defer your dom manipulation until after the if is rendered, you run the risk of the if going away and coming back (at which point your css code will not be run again).
A much better way to do this would be to setup a watch and add your css in a watch, or better still, use ng-class and add the css in your template.
The angular framework needs to have $scope.$apply() called in order to update the bindings and expand the template. $timeout() is an async wrapper which assumes that changes were made outside angular world and it calls $scope.$apply() as a final step. in your case, using $scope.$apply(); directly, immediately before your element call achieves the desired effect.
I have already read the
Compilation process, and directive matching
on AngularJS Doc.
but I really didn't understand the directives.
Example:
I have static html:
<div class="test test2" cid="549" sid="a5e3c4f8a9">text-text-text</div>
when I do it manually, I know it will only created and called one time at browser's parse time.
but what happens when I create a directive with the same dom element ?
<x my-directive>text-text-text</x>
is this the same effect?
I am asking such a newbie question, because I am using over 200 elements on my html page.
If I change them to single directive: for sure it will be much more easier to manage them.
and its no problem if its only slow at browser's compile time but what happend in run time?
and I am sorry, if the qustion is not pro enought. I am just new to Stackoverflow.
Thank You
Daniel
If I understand you correctly, you want to know how AngularJS creates a directive and how many times your directive methods are called.
When you create a directive (with module.directive('myDirective', ...)), you are really just creating a definition. Every time you use that directive (like <div my-directive>), AngularJS will run through the process described in the guide: that is, it will compile and link each use. It has to be this way because the directive doesn't exist in isolation; it exists not only in the $scope in which it was called, but also it can make use of element attributes and transcluded contents. The definition occurs once, but each instance is compiled and linked.
Once the directive is created, it's technically done; if you don't set up any $watch or $observe or event bindings, your "directive" is now just whatever's in the DOM at the end of your link function - there's no more computation. In other words, what happens after compilation and linking is entirely up to you.
So back to your example: if you use 200 of the same directive on the page, the directive will be defined once, but all 200 will be compiled and linked separately. But I'm not really sure what you're implying by asking. What's the question behind your question?
I have an HTML file which is linked to CSS file and also to JavaScript file.
Is JavaScript executed first and then the CSS is applied, or vice versa ?
Is there any way to change the order ?
Thanks !
It's generally considered a good idea to import your scripts as late as possible, and your stylesheets as early as possible. If possible, in fact, you should stick all your script imports at the very end of the <body>. I find that problematic when there are components pulled into the page that want to be able to drop little script blocks that reference jQuery (for example).
If your stylesheets are first, that helps make sure the browser applies styles before showing anything to the user. Conversely, by including scripts last, you defer that potentially slow script processing until after the point where the user gets to see something on the screen.
The JavaScript gets executed when the <script> element is parsed. Some of the JS might set up event handlers to run some JS when events happen.
CSS is applied to the live DOM. Changes to the DOM get CSS applied automatically. Changes to CSS apply to the whole DOM automatically.
Yahoo's research into speeding-up page loading times should be very helpful, and they explain things much clearer than I can.
http://developer.yahoo.com/performance/rules.html