javascriptjqueryember.jscoffeescriptevented-io

Ember.js Evented Controller triggering an event


I am trying to trigger an event from an Ember.js controller so the listening views can update themselves. Here is the Coffeescript.

window.CMS.EdmController = Ember.ObjectController.extend Ember.Evented,
  actions:
   save_edm: ->
     postData = $('#edm_form').serialize()
     $.ajax(
       url: 'cms2/update_edm',
       type: 'POST',
       data: postData
       )
       .done ->
         console.log(@)
         @trigger('saveEdmSuccessful')

It fails with an error Object #Object has no method trigger. The @ in the .done function refers to the jQuery post object and not the controller.

How do I get the reference to the parent controller object from inside a jQuery callback?

Any guidance would be appreciated.


Solution

  • I did try to compile your Coffeescript and ended up getting the following code as output:

    window.CMS.EdmController = Ember.ObjectController.extend(Ember.Evented, {
      actions: {
        save_edm: function() {
          var postData;
          postData = $('#edm_form').serialize();
          return $.ajax({
            url: 'cms2/update_edm',
            type: 'POST',
            data: postData
          }).done(function() {
            console.log(this);
            return this.trigger('saveEdmSuccessful');
          });
        }
      }
    });
    

    And the solution to the problem you are facing is not related to ember.js, but the way Javascript closures work. A solution to the above problem would be:

    window.CMS.EdmController = Ember.ObjectController.extend(Ember.Evented, {
      actions: {
        save_edm: function() {
          var postData;
          postData = $('#edm_form').serialize();
          return $.ajax({
            url: 'cms2/update_edm',
            type: 'POST',
            data: postData
          }).done($.proxy(function() {
            console.log(this);
            return this.trigger('saveEdmSuccessful');
          },this));
        }
      }
    });
    

    Notice how I've replaced your .done handler from a function call to a proxy call. This makes sure that when the callback is executed, the context is updated to reflect the current this.

    To understand further about the behaviour of this in JavaScript, read this article.

    For your reference, here is the CoffeeScript equivalent of my solution:

    window.CMS.EdmController = Ember.ObjectController.extend Ember.Evented,
      actions:
       save_edm: ->
         postData = $('#edm_form').serialize()
         $.ajax(
           url: 'cms2/update_edm',
           type: 'POST',
           data: postData
           )
           .done(
              $.proxy ->
                console.log(@)
                @trigger('saveEdmSuccessful')
              @
           )