In my simple project I have 2 views - a line item view (Brand) and App. I have attached function that allows selecting multiple items:
var BrandView = Backbone.V
You can use Backbone object as the event bus.
This approach is somewhat cleaner but still relies on Global Backbone object though
var view1 = Backbone.View.extend({
_onEvent : function(){
Backbone.trigger('customEvent');
}
});
var view2 = Backbone.View.extend({
initialize : function(){
Backbone.on('customEvent', this._onCustomEvent, this);
},
_onCustomEvent : function(){
// react to document edit.
}
});
Use the same model objects. AppView could be initialized with a collection, and BrandView initialized with one model from that collection. When attributes of a branch object change, any other code that has a reference to that model can read it.
So lets so you have some brands that you fetch via a collection:
var brands = new Brands([]);
brands.fetch();
Now you make an AppView, and an array of BrandView's for each model.
var appView = new AppView({brands: brands});
var brandViews = brands.map(function(brand) {
return new BrandView({brand: brand});
});
The appView and the brandViews now both have access to the same model objects, so when you change one:
brands.get(0).selected = true;
Then it changes when accessed by the views that reference it as well.
console.log(appView.brands.get(0).selected); // true
console.log(brandViews[0].brand.selected) // true
Ignoring the problems with this that you already mention in your post, you can bind and trigger events to/from the global Backbone.Event object, which will allow anything to talk to anything else. Definitely not the best solution, and if you have views chatting with one another then you should consider refactoring that. But there ya go! Hope this helps.
Here is my case with a similar need: Backbone listenTo seemed like a solution to redirect to login page for timed out or not authenticated requests.
I added event handler to my router and made it listen to the global event such as:
Backbone.Router.extend({
onNotAuthenticated:function(errMsg){
var redirectView = new LoginView();
redirectView.displayMessage(errMsg);
this.loadView(redirectView);
},
initialize:function(){
this.listenTo(Backbone,'auth:not-authenticated',this.onNotAuthenticated);
},
.....
});
and in my jquery ajax error handler:
$(document).ajaxError(
function(event, jqxhr, settings, thrownError){
.......
if(httpErrorHeaderValue==="some-value"){
Backbone.trigger("auth:not-authenticated",errMsg);
}
});
You might want to have a read of this discussion of Backbone pub/sub events:
http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/
I like to add it in as a global event mechanism:
Backbone.pubSub = _.extend({}, Backbone.Events);
Then in one view you can trigger an event:
Backbone.pubSub.trigger('my-event', payload);
And in another you can listen:
Backbone.pubSub.on('my-event', this.onMyEvent, this);
I use what Addy Osmani calls the mediator pattern http://addyosmani.com/largescalejavascript/#mediatorpattern. The whole article is well worth a read.
Basically it is an event manager that allows you to subscribe to and publish events. So your AppView would subscript to an event, i.e. 'selected'. Then the BrandView would publish the 'selected' event.
The reason I like this is it allows you to send events between views, without the views being directly bound together.
For Example
var mediator = new Mediator(); //LOOK AT THE LINK FOR IMPLEMENTATION
var BrandView = Backbone.View.extend({
toggle_select: function() {
...
mediator.publish('selected', any, data, you, want);
return this;
}
});
var AppView = Backbone.View.extend({
initialize: function() {
mediator.subscribe('selected', this.delete_selected)
},
delete_selected: function(any, data, you, want) {
... do something ...
},
});
This way your app view doesn't care if it is a BrandView or FooView that publishes the 'selected' event, only that the event occured. As a result, I find it a maintainable way to manage events between parts of you application, not just views.
If you read further about the 'Facade', you can create a nice permissions structure. This would allow you to say only an 'AppView' can subscribe to my 'selected' event. I find this helpful as it makes it very clear where the events are being used.