43

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.

Yehuda Katz
  • 28,535
  • 12
  • 89
  • 91
Marc Hughes
  • 5,808
  • 3
  • 36
  • 46

5 Answers5

64

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

Yehuda Katz
  • 28,535
  • 12
  • 89
  • 91
Roy Daniels
  • 6,309
  • 2
  • 27
  • 29
  • 10
    Within your override of didInsertElement, you can reference `this.$()` to get a handle to the jquery wrapper for the DOM element. – Luke Melia Jan 17 '12 at 14:11
  • 3
    Marc: You might find this article useful as well. It helped me back in the day when I had to get JUI and SC2 working. NOTE: Some of the api might have changed since this article was written so it might not be cut and paste code. [http://yehudakatz.com/2011/06/11/using-sproutcore-2-0-with-jquery-ui/](http://yehudakatz.com/2011/06/11/using-sproutcore-2-0-with-jquery-ui/) – Roy Daniels Jan 17 '12 at 14:20
  • Thanks a lot! That this answer plus those two comments really helped me figure this out. I'm impressed with the EmberJS community support so far. – Marc Hughes Jan 17 '12 at 15:56
  • I'm glad I found this. Thanks @LukeMelia, I was wondering how to get a reference to the DOM element. – Calvin Jan 19 '12 at 00:32
  • 4
    I have a view in which I render an array of models in its template. I put a breakpoint on the didInserElement function and I can see that it fires before the list of elements is rendered. I need to execute some logic **after each change**. Is there any way to accomplish this? – miguelcobain Mar 08 '13 at 12:44
  • miguelcobain - I have the same issue, have you figured it out? I need to perform jQuery logic on a list of items that load after didInsertElement fires on the view. – jdcravens Mar 20 '13 at 03:40
  • Nevermind ... the solution is very well documented here: http://stackoverflow.com/questions/13760733/ember-js-using-a-handlebars-helper-to-detect-that-a-subview-has-rendered/13857859#13857859 – jdcravens Mar 20 '13 at 03:55
3

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
    });
}
Jyoti
  • 94
  • 1
  • 9
1

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,

  1. The component's element has been both created and inserted into the DOM.
  2. The component's element is accessible via the component's $() 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

XY L
  • 25,431
  • 14
  • 84
  • 143
1

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

NullVoxPopuli
  • 61,906
  • 73
  • 206
  • 352
0

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();
  }

});
sergserg
  • 21,716
  • 41
  • 129
  • 182