10
votes

I'm recently evaluating a JavaScript framework to be used for our next project. I really like Ember. But in our application, we would need an eventing mechanism from the data layer to notify the controller layer that something has changed. I know one could use obersevers in Ember, for example,:

person.addObserver('fullName', function() {
  // deal with the change
});

But I like more in Backbone.Events that you could subscribe or publish an event, specifically:

var object = {};

_.extend(object, Backbone.Events);

object.on("alert", function(msg) {
  alert("Triggered " + msg);
});

object.trigger("alert", "an event");

Anybody has an idea whether that's doable in EmberJS?

To also give you some background about my question, our application is a real-time application. So from time to time, the backend RESTful service will fire an event to the client side (JavaScript side). I would like to have a data layer which encapsulate the access to the backend RESTful service, but also keeps a cache. I hope EmberJS.Data could help me with that (that's a separate question I want to find answers). With that, I would like also the cache to be updated whenever a change happened from the backend RESTful service. Once the cache object is updated, I would like the Controller layer to be notified. This is basically why I need some eventing mechanism in JavaScript side.

Note that the reason I don't want to use the Observers is that sometimes, an event could mean I have to perform an action, i.e. load up a message, or indicate that a voice call is coming. The backbone way seems more natuarl to me.

Thanks

2

2 Answers

11
votes

Since commit 2326580 - which is available since v0.9.6 - there is an Ember.Evented Mixin, see http://jsfiddle.net/qJqzm/.

var handler = Ember.Object.create({
    otherEvent: function() {
        console.log(arguments);
    }
});

var myObject = Ember.Object.create(Ember.Evented, {
    init: function() {
        this._super();
        this.on('alert', this, 'alert');
    },
    alert: function() {
        console.log(arguments);
    }
});
myObject.on('otherEvent', handler, 'otherEvent');

myObject.fire('alert', {
    eventObject: true
});
myObject.fire('otherEvent', {
    first: true
}, {
    second: true
});​
8
votes

If you want a general purpose publish/subscribe hub, you can leverage trigger/on from Evented (as pangratz said) with a little syntactic sugar. Here's what I am doing:

App.Hub = Ember.Object.create({
  init: function(){
    this.set('HUB', Ember.Object.createWithMixins(Ember.Evented, {}));
  },

  publish: function(){
    var hub = this.get('HUB');
    return hub.trigger.apply(hub, arguments);
  },

  subscribe: function(){
    var hub = this.get('HUB');
    return hub.on.apply(hub, arguments);
  }
});

Then, to use it in your application:

App.Hub.subscribe('test-started', function(name){ 
  console.log("Test " + name + " started");
});

...

App.Hub.publish('test-started', 'Biology I');
App.Hub.publish('test-started', 'Calculus');