Reputation: 15742
I got following nested View structure:
LayoutView
- SidebarView
- ContactListView
- ContactItemView
- ContentView
Now imagine following situation:
A user clicks on a ContactItem. Now the ContactItem should call an event or something else which renders the profile of the clicked contact in the ContentView.
I have no idea how I could do this without breaking the flexibility...
Upvotes: 1
Views: 664
Reputation: 1300
Check out Backbone.Courier. It is a light weight backbone plugin built for exactly the kind of "event bubbling" scenario you describe, making it easy for child views to communicate with parents, grandparents, etc., without need for trigger chains or global event aggregators.
Upvotes: 0
Reputation: 2925
One approach is to use is an event aggregator which enables your views to subscribe to certain events. This will allow you to decouple your views from each other. Your views don't need to know about each other, they just need to keep track of certain events. For a great tutorial on how to do this see Derick Bailey's excellent post on the topic.
Upvotes: 2
Reputation: 7356
You probably want to use Events to hook them together, rather than having the ContactItemView directly call the ContentView. As you're creating the views, each parent view can bind to the child view's events. Then when the click happens, it will bubble up through the chain until the appropriate view handles it.
Here's a simple example to show the general idea. I'm presenting this in the order that the event bubbling happens, which is hopefully a little bit clearer.
First, the ContactItemView gets the DOM click event and triggers a Backbone event for it.
//ContactItemView.js
events : {
"click .contactName" : "click"
},
click : function(evt){
this.trigger("clicked", this);
}
The ContactListView can listen for that and republish it:
//ContactListView.js
render : function(){
var itemView = new ContactItemView();
itemView.on("clicked", this.itemClicked, this);
},
itemClicked : function(item){
this.trigger("clicked", item);
}
The SidebarView listens for that event, and actually knows what to do with it:
//SidebarView.js
render: function(){
var listView = new ContactListView();
this.contentView = new ContentView();
listView.on(clicked, this.contactItemClicked, this);
},
contactItemClicked : function(contactItem){
this.contentView.showMeAContact(contactItem.model); //or whatever
}
This way your ContactItemView doesn't know anything about the parent views, so it can be more flexible. The downside is it's a lot of boilerplate code. Maybe someone else will have a cleaner approach, but this does the trick for me.
Upvotes: 2