Wondered what's the best way to detect the finish of page loading/bootstrapping, when all directives done compiling/linking.
Any event already there? Should i overload the bootstrap function?
Wondered what's the best way to detect the finish of page loading/bootstrapping, when all directives done compiling/linking. Any event already there? Should i overload the bootstrap function? |
||||
|
Just a hunch: why not look at how the ngCloak directive does it? Clearly the ngCloak directive manages to show content after things have loaded. I bet looking at ngCloak will lead to the exact answer... EDIT 1 hour later: Ok, well, I looked at ngCloak and it's really short. What this obviously implies is that the compile function won't get executed until {{template}} expressions have been evaluated (i.e. the template it loaded), thus the nice functionality of the ngCloak directive. My educated guess would be to just make a directive with the same simplicity of ngCloak, then in your compile function do whatever you want to do. :) Place the directive on the root element of your app. You can call the directive something like myOnload and use it as an attribute my-onload. The compile function will execute once the template has been compiled (expressions evaluated and sub-templates loaded). EDIT, 23 hours later: Ok, so I did some research, and I also asked my own question. The question I asked was indirectly related to this question, but it coincidentally lead me to the answer that solves this question. The answer is that you can create a simple directive and put your code in the directive's link function, which (for most use cases, explained below) will run when your element is ready/loaded. Based on Josh's description of the order in which compile and link functions are executed,
From this we can conclude that we can simply make a directive to execute our code when everything is ready/compiled/linked/loaded:
Now what you can do is put the ngElementReady directive onto the root element of the app, and the
It's that simple! Just make a simple directive and use it. ;) You can further customize it so it can execute an expression (i.e. a function) by adding
Then you can use it on any element:
Just make sure you have your functions (e.g. bodyIsReady and divIsReady) defined in the scope (in the controller) that your element lives under. Caveats: I said this will work for most cases. Be careful when using certain directives like ngRepeat and ngIf. They create their own scope, and your directive may not fire. For example if you put our new ngElementReady directive on an element that also has ngIf, and the condition of the ngIf evaluates to false, then our ngElementReady directive won't get loaded. Or, for example, if you put our new ngElementReady directive on an element that also has a ngInclude directive, our directive won't be loaded if the template for the ngInclude does not exist. You can get around some of these problems by making sure you nest the directives instead of putting them all on the same element. For example, by doing this:
instead of this:
The ngElementReady directive will be compiled in the latter example, but it's link function will not be executed. Note: directives are always compiled, but their link functions are not always executed depending on certain scenarios like the above. EDIT, a few minutes later: Oh, and to fully answer the question, you can now
EDIT, even more few minutes later: @satchmorun's answer works too, but only for the initial load. Here's a very useful SO question that describes the order things are executed including link functions, EDIT, five months later, Oct 17 at 8:11 PST: This doesn't work with partials that are loaded asynchronously. You'll need to add bookkeeping into your partials (e.g. one way is to make each partial keep track of when its content is done loading then emit an event so the parent scope can count how many partials have loaded and finally do what it needs to do after all partials are loaded). EDIT, Oct 23 at 10:52pm PST: I made a simple directive for firing some code when an image is loaded:
EDIT, Oct 24 at 12:48am PST: I improved my original
For example, use it like this to fire
Evaluate as many expressions as you want, and make the last expression
This only works the first time an element is loaded, not on future changes. It may not work as desired if a EDIT, Oct 31 at 7:26pm PST: Alright, this is probably my last and final update. This will probably work for 99.999 of the use cases out there:
Use it like this
Of course, it can probably be optimized, but I'll just leave it at that. requestAnimationFrame is nice. |
|||||||||||||||||||||
|
In the docs for
So if you have some module that is your app:
You can run stuff after the modules have loaded with:
EDIT: Manual Initialization to the rescueSo it's been pointed out that the I took another look at manual initialization, and it seems that this should do the trick. I've made a fiddle to illustrate. The HTML is simple:
Note the lack of an As usual, a module is created:
And here's the directive:
We're going to replace the I've added a compile function that returns both pre and post link functions so we can see when these things run. Here's the rest of the code:
Before we've done anything, there should be no elements with a class of
It's pretty straightforward. When the document is ready, call In fact, if you attach a If you run the fiddle and watch the console, you'll see the following:
|
|||||||||||||||||||||
|
Wanted to add one more realization I had about my own question: Angular hasnt provided a way to signal when a page finished loading, maybe because 'finished' depends on your application. for example, if you have hierarchical tree of partials, one loading the others. 'finish' would mean that all of them have been loaded. Any framework would have a hard time analyzing your code and understanding that everything is done, or still waited upon.For that, you would have to provide application-specific logic to check and determine that. thanks Lior |
|||
|
I have come up with a solution that is relatively accurate at evaluating when the angular initialisation is complete. The directive is:
That can then just be added as an attribute to the It works by assuming that the application is initialised when there are no more $digest cycles. $watch is called every digest cycle and so a timer is started (setTimeout not $timeout so a new digest cycle is not triggered). If a digest cycle does not occur within the timeout then the application is assumed to have initialised. It is obviously not as accurate as satchmoruns solution (as it is possible a digest cycle takes longer than the timeout) but my solution doesn't need you to keep track of the modules which makes it that much easier to manage (particularly for larger projects). Anyway, seems to be accurate enough for my requirements. Hope it helps. |
|||||||||
|
If you are using Angular UI Router, you can listen for the "$viewContentLoaded - fired once the view is loaded, after the DOM is rendered. The '$scope' of the view emits the event." - Link
|
|||||||||||||||||||||
|
i observe DOM manipulation of angular with JQuery and i did set a finish for my app (some sort of predefined and satisfactory situation that i need for my app-abstract) for example i expect my ng-repeater to produce 7 result and there for i will set an observation function with the help of setInterval for this purpose .
|
|||||||||
|
According to the Angular team and this Github issue:
Based on this, it seems this is currently not possible to do in a reliable way, otherwise Angular would have provided the event out of the box. Bootstrapping the app implies running the digest cycle on the root scope, and there is also not a digest cycle finished event. According to the Angular 2 design docs:
According to this, the fact that this is not possible is one the reasons why the decision was taken to go for a rewrite in Angular 2. |
|||
|
If you don't use ngRoute module, i.e. you don't have $viewContentLoaded event. You can use another directive method:
Accordingly to trusktr's answer it has lowest priority. Plus $timeout will cause Angular to run through an entire event loop before callback execution. $rootScope used, because it allow to place directive in any scope of the application and notify only necessary listeners.
|
||||
|
I had a fragment that was getting loaded-in after/by the main partial that came in via routing. I needed to run a function after that subpartial loaded and I didn't want to write a new directive and figured out you could use a cheeky Controller of parent partial:
HTML of subpartial
|
|||
|
These are all great solutions, However, if you are currently using Routing then I found this solution to be the easiest and least amount of code needed. Using the 'resolve' property to wait for a promise to complete before triggering the route. e.g.
}) |
|||||
|
may be i can help you by this example In the custom fancybox I show contents with interpolated values. in the service, in the "open" fancybox method, i do
the $compile returns compiled data. you can check the compiled data |
|||
|
If you want to generate JS with server-side data (JSP, PHP) you could add your logic to a service, that will be loaded automatically when your controller is loaded. Additionally, if you want to react when all directives are done compiling/linking, you could add the appropriate proposed solutions above in the initialization logic.
|
|||
|