Search code examples
backbone.jsbindingviewunderscore.jsmodels

How can I bind an event on an element from another view in backbone


The i'm trying to attach event is from another view

I have two views

  • headerView
  • contentView

My headerView use a Header model, everytime the model change, i render() my headerView.

Like most of iPhone's app, I use two button in my header for navigation, depending on where you are, images can changes.

This is why when I initialize a random contentView, I can access the model in headerView and change a property.

The last thing I need to do is to create a click event for this button.

I'm trying to bind in my content view (it makes more sense)

events: {
   "click .h_left": "newLocation",
}

Events aren't firing, it's only the case if I place this events in headerView, is there a recommended clean solution to do so ?


Solution

  • The whole point of Backbone.View is to encapsulate the modifications and event handling of a DOM subtree into a View class. As such, Backbone doesn't support your scenario.

    You have a few options of achieving the same end result.

    The simple (but wrong) way: Use jQuery to listen to the header's events:

    var ContentView = Backbone.View.extend({
       initialize: function() {
         $(".h_left").on('click', this.newLocation);
       },
    
       remove: function() {
         $(".h_left").off('click', this.newLocation);
         Backbone.View.prototype.remove.call(this);
       }
    });
    

    This breaks the encapsulation of your header element, and tightly couples the content view to the header element's implementation. In other words: spaghetti.

    The correct way: Use a mediator to pass messages from the header to other views:

    var HeaderView = Backbone.View.extend({
      events: {
        "click .h_left": "onLeftButtonClick"
      },
    
      onLeftButtonClick: function() {
        //You can use the root Backbone object as a global event bus
        //Publish a message
        Backbone.trigger('header:leftbutton');
      }
    });
    
    var ContentView = Backbone.View.extend({
       initialize: function() {
         //Subscribe to a message. If you use listenTo, the subscription is 
         //automatically cleared when your content view is destroyed.
         this.listenTo(Backbone, 'header:leftbutton', this.newLocation);
       },
    
       newLocation: function() {
         //..
       }
    });