bodokaiser
bodokaiser

Reputation: 15742

Backbone: How can I call a parent parent view?

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

Answers (3)

Brave Dave
Brave Dave

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

Benjen
Benjen

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

Brian Reischl
Brian Reischl

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

Related Questions