Reputation: 3268
I'm using the jQuery DataTables plugin to render data in Ember. I'm running into classic race condition issues and some part of my understanding of Ember and the Ember run-loop must be incomplete. Here's what's happening.
<table>...<tbody>{{#each user in model}}...
didInsertElement
method, and wrap it in Ember.run.scheduleOnce('afterRender', function() { $('#myTable').DataTable(); })
Uncaught Error: Cannot perform operations on a Metamorph that is not in the DOM.
I have looked at similar StackOverflow posts on this:
But these fixes don't seem to work. I suspect that DataTables is trying to update the DOM before Ember has finished rendering it, but then why doesn't my called Ember.run.scheduleOnce('afterRender', ...)
address that?
Strangely, I can get it work by doing the following:
Old (Race Condition) Code in View:
didInsertElement: function() {
Ember.run.scheduleOnce('afterRender', function() {
$('#orgUsers').DataTable();
});
}
New Working Code in View:
didInsertElement: function() {
setTimeout(function() {
$('#orgUsers').DataTable();
}, 0);
}
Note that I have specified a javascript setTimeout
delay of 0 seconds! But this works every time.
Can someone help me understand (1) why does wrapping this in setTimeout()
solve all my problems, (2) what is the "Ember Way" to handle this? Thanks!
Upvotes: 3
Views: 466
Reputation: 6947
I would expect this to work:
Ember.run.next(this, function() {
Ember.$('#orgUsers').DataTable();
});
This is preferable to your setTimeout
code. Ember will schedule your function for the next run loop. didInsertElement
is called from a task in the render
queue. Your call to scheduleOnce
goes into the afterRender
queue, which is "downstream" from the render
queue, but in the same loop iteration.
Using run.next
will schedule the task in a new run loop, so there won't be lifecycle issues in the current loop.
Upvotes: 2