UPDATE : Please use the code found in my follow-up.
Derick Bailey wrote a great post decoupling Backbone Views from one another through the use of an Event Aggregator.
I wanted to use this without passing in the dispatcher into all these Views, Models, etc. To accomplish this I came
up with the following:
//namespace our extensions
var BackboneExt = BackboneExt || function() {
var backbonePrototypes = [
Backbone.Collection.prototype,
Backbone.Model.prototype,
Backbone.View.prototype,
Backbone.Router.prototype
];
var extensions = {
dispatcher : _.extend({}, Backbone.Events,{cid : 'dispatcher'}),
wrappedEvents : function(localEvents) {
var local = localEvents || _.extend({},Backbone.Events);
//note that 'this' is the Backbone implementation
return {
dispatcher : BackboneExt.dispatcher,
trigger : function() {
var args = _.toArray(arguments);
// this._callbacks is an internal collection
// currently backbone could
if( this._callbacks ) {
local.trigger.apply(this,args);
}
BackboneExt.dispatcher.trigger.apply(BackboneExt.dispatcher,args);
return this;
}
};
},
extendBackbone : function() {
var self = this;
if( self.isExtended ) {
return;
}
_.each(backbonePrototypes,function(proto) {
_.extend(proto, self.autoBinder, self.wrappedEvents());
});
}
};
return extensions;
}();
BackboneExt.extendBackbone();
Note that dispatcher is now exposed in any of the Backbone components. We just overwrite the default Backbone.Events.trigger
with our own that composes the local trigger with the global (dispatcher) trigger.
trigger
This keeps my Backbone components blissfully ignorant of its subscriber(s):
// some simple jquery notification component
BackboneExt.dispatcher.bind('mynamespaced:event', function(args) {
$('#messages').append(args.message);
});
// some Backbone.Model
var model = new SomeModel({
// ...
someMethod : function() {
this.trigger('mynamespaced:event',{ message : 'something happened' });
}
});
bind
This can work the other way, too, but the Backbone components need to explicitly bind to the exposed dispatcher:
//inside Backbone.Model initializer
var model = new SomeModel( {
initialize : function() {
dispatcher.bind('someglobalevent:happened', this.someMethod);
}
someMethod : function() { ... }
});
BackboneExt.dispatcher.trigger('someglobalevent:happened', 'something happened'); //calls 'someMethod' in model
Posted
08-14-2011 8:21 PM
by
Michael Nichols