AlexBrand
AlexBrand

Reputation: 12399

Calling view function from another view - Backbone

I have the following views in my application. Basically I want to call show_house() in App.MapView when the li of the App.HouseListElemView is clicked.

What would be the best way of doing this?

App.HouseListElemView = Backbone.View.extend({
    tagName: 'li',
    events: {
        'click': function() {
            // call show_house in App.MapView
        }
    },
    initialize: function() {
        this.template = _.template($('#house-list-template').html());
        this.render();
    },
    render: function() {
        var html = this.template({model: this.model.toJSON()});
        $(this.el).append(html);
    },   
});

App.MapView = Backbone.View.extend({
   el: '.map',
   events: {
       'list_house_click': 'show_house',
   },
   initialize: function() {
       this.map = new GMaps({
           div: this.el,
           lat: -12.043333,
           lng: -77.028333,   
       });
       App.houseCollection.bind('reset', this.populate_markers, this);
   },
   populate_markers: function(collection) {
       _.each(collection.models, function(house) {
            var html = 'hello'
            this.map.addMarker({
                lat: house.attributes.lat,
                lng: house.attributes.lng,
                infoWindow: {
                    content: html,
                }                
            });
       }, this);
   },
   show_house: function() {
       console.log('show house');
   }
});

Upvotes: 8

Views: 12291

Answers (1)

mu is too short
mu is too short

Reputation: 434616

The current house is really part of your application's global state so create a new model to hold your global application state:

var AppState  = Backbone.Model.extend({ /* maybe something in here, maybe not */ });
var app_state = new AppState;

Then your HouseListElemView can respond to clicks by setting a value in app_state:

App.HouseListElemView = Backbone.View.extend({
    //...
    events: {
        'click': 'set_current_house'
    },
    set_current_house: function() {
        // Presumably this view has a model that is the house in question...
        app_state.set('current_house', this.model.id);
    },
    //...
});

and then your MapView simply listens for 'change:current_house' events from app_state:

App.MapView = Backbone.View.extend({
    //...
    initialize: function() {
        _.bindAll(this, 'show_house');
        app_state.on('change:current_house', this.show_house);
    },
    show_house: function(m) {
        // 'm' is actually 'app_state' here so...
        console.log('Current house is now ', m.get('current_house'));
    },
    //...
});

Demo: http://jsfiddle.net/ambiguous/sXFLC/1/

You might want current_house to be an actual model rather than simply the id of course but that's easy.

You'll probably be able to find all sorts of other uses for app_state once you have it. You can even add a little bit of REST and AJAX and get persistence for your application settings pretty much for free.

Events are the usual solution to every problem in Backbone and you can make models for anything you want, you can even make temporary models strictly for gluing things together.

Upvotes: 14

Related Questions