How do I run a function after an Ember View is inserted into the DOM?
Here\'s my use-case: I\'d like to use jQuery UI sortable to allow sorting.
Ember 2.x: View is deprecated, use component instead
You have to understand the component's lifecycle to know when does certain things happen.
As components are rendered, re-rendered and finally removed, Ember provides lifecycle hooks that allow you to run code at specific times in a component's life.
https://guides.emberjs.com/v2.6.0/components/the-component-lifecycle/
Generally, didInsertElement
is a great place to integrate with 3rd-party libraries.
This hook guarantees two (2) things,
$()
method.In you need JavaScript to run whenever the attributes change
Run your code inside didRender
hook.
Once again, please read the lifecycle documentation above for more information
You need to override didInsertElement
as it's "Called when the element of the view has been inserted into the DOM. Override this function to do any set up that requires an element in the document body."
Inside the didInsertElement
callback, you can use this.$()
to get a jQuery object for the view's element.
Reference: https://github.com/emberjs/ember.js/blob/master/packages/ember-views/lib/views/view.js
Starting with Ember 3.13, you can use components that inherit from Glimmer, and this example below shows what that could look like:
import Component from '@glimmer/component';
import { action } from '@ember/object';
/* global jQuery */
export default class MyOctaneComponent extends Component {
@action configureSorting(element) {
jQuery(element).sortable();
}
}
<div {{did-insert this.configureSorting}}>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
These view style components don't have lifecycle hooks directly, instead, you can use render-modifiers to attach a function. Unofficial introduction to modifiers can be found here
The benefit of this is that, it's clearer what the responsibilities of the template are and become.
Here is a runnable codesandbox if you want to play around with this: https://codesandbox.io/s/octane-starter-ftt8s
You need to fire whatever you want in the didInsertElement
callback in your View:
MyEmberApp.PostsIndexView = Ember.View.extend({
didInsertElement: function(){
// 'this' refers to the view's template element.
this.$('table.has-datatable').DataTable();
}
});
You can also use afterRender method
didInsertElement: function () {
Ember.run.scheduleOnce('afterRender', this, function () {
//Put your code here what you want to do after render of a view
});
}