Has someone any advice?
You could use the ādidTransitionā action of your route. This will fire after the transition to the route completes.
No, didTransition will be fired before didInsertElement, not after render complete.
didInsertElement() {
Ember.run.scheduleOnce('afterRender', this, () => {
// ...
});
}
Where I can place didInsertElement since viewClass was deprecated.
A template has many components. After these component rendered, I want to do something . I can call didInsertElement in a view of template before.
But now, how can I do this?
Try placing Jasonās suggested run loop code in the didTransition action that I mentioned before. Or, didInsertElement is available in your components so you could put it there. However, that might not suit as you might want your after render code somewhere outside of a component so you have access to the model without having to pass it in via attributes to the component.
Thank you.
Merged solution:
ApplicationRoute::didTransition => scheduleOnce(āafterRenderā)
You should note that scheduling in afterRender
at this point in the process DOES NOT guarantee that it happens after rendering is complete. If the runloop empties before rendering is finished, this will fire sooner. 99.9% of the time you will never know the difference.
You can still use top level views in ember, or utilize a component to wrap your routeās template, and use the didInsertElement hook there.
Using component to wrap routeās template is specific, not for purpose, and ApplicationView::didInsertElement too.
I donāt understand the runloop empties before rendering is finished
.
Using component to wrap routeās template is specific, not for purpose, and ApplicationView::didInsertElement too.
Yes, but both of these are common and acceptable practices. This is the way you tell your app to do something after render.
I donāt understand the runloop empties before rendering is finished.
The runloop is a set of queues. The queue can finish processing before rendering is complete. Itās not a guarantee that the afterRender
queue runs after render is complete, just that it runs after the render
queue is complete. The render
queue is where tasks pertaining to rendering are scheduled, but what it considers to be render and what your browser considers to be render arenāt perfectly aligned.
The queues are for organizing the order of operations, they donāt guarantee timing. By using didInsertElement
along with afterRender
you guarantee yourself both timing and correct organization.
Thank you for your explanation.
There is a example.
Say that I need to scroll component content with using iscroll.js.
If the data of component content is explicit. use ApplicationRoute::didTransition => scheduleOnce(āafterRenderā, triggerSomethingForIscroll) It seem not working properly sometimes like you say.
use Component::didInsertElement => scheduleOnce(āafterRenderā, doIscrollFunction) It works fine.
But if the data of component content contains some asynchronous data which is from model relationships.
Is it right that the above way will not wait until asynchronous data loaded, so it will result to that iscroll get wrong height of content at the same time.
This is what I encountered.
Finally, does it exist a way to know render complete for any route transition globally?
@imaxhung One strategy I used to combat a similar problem was to wait to initialize iscroll in a didInsertElement afterRender callback until the content was actually in the DOM. Count the number of elements in the DOM where you expect them. If the count is greater than zero, initialize the plugin.
I generally just create a view for the route (like app/views/whatever.js
) and add an afterRender
function to the controller
export default Ember.View.extend({
didInsertElement: function() {
if(this.get('controller').afterRender) {
this.get('controller').afterRender();
}
}
});
~