Calling jQuery plugin with EmberJS creates race conditions

I am using jQuery DataTables plugin to render data in Ember. I'm running into classic race problems and some of my understanding of Ember and the Ember Run-loop must be incomplete. Here's what's going on.

  • I have dumped data table into my template using <table>...<tbody>{{#each user in model}}...

  • In my view, I call the DataTables library in a method didInsertElement

    and terminate it inEmber.run.scheduleOnce('afterRender', function() { $('#myTable').DataTable(); })

  • The first time I access this page code, I get the following error: Uncaught Error: Cannot perform operations on a Metamorph that is not in the DOM.

  • If I access it again, it works fine.

I looked at similar StackOverflow posts:

But these fixes don't seem to work. I suspect DataTables is trying to update the DOM before Ember has finished rendering it, but why isn't my address Ember.run.scheduleOnce('afterRender', ...)

called?

Strange, I can get it to 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 delay of setTimeout

0 seconds! But it works every time.

Can anyone please help me understand (1) why wrapping this in setTimeout()

solves all my problems, (2) what is the "Horrible way" to deal with this? Thank!

+3


source to share


1 answer


I expect this to work:

Ember.run.next(this, function() {
    Ember.$('#orgUsers').DataTable();
});

      



This is preferred over your code setTimeout

. Ember will schedule your function for the next loop. didInsertElement

called from a task in the queue render

. Your call scheduleOnce

goes to a queue afterRender

that is "descending" from the queue render

, but in the same loop iteration.

Usage will run.next

schedule the task in a new startup cycle, so there will be no life cycle issues in the current cycle.

+2


source







All Articles