Question

I have a collection instance and then a collection view instance on page load that populates from the server a region and wineries from that region.

This is being called on my home page in a jQuery ready function...

var regionWineriesList = new RegionWineriesList();
var regionWineriesListView = new RegionWineriesListView({collection: regionWineriesList, map: Map.map});
regionWineriesList.fetch({
    success: function(response) {
        $('.wineries-scroll').prepend(regionWineriesListView.render().el);
    }
});

This is working great.

I also have an autocomplete view that when clicked, does a fetch for a new set of data. It is in the findWineries() function.

var RegionsView = Backbone.View.extend({

el: 'body',

initialize: function(options) {
    this.region_input = $('input#RegionLocation');
    this.winery_input = $('input#WinerySearchHome');
},

events: {
    'click input#RegionLocation': 'autoCompleteSetup',
    'click .pulldown-arrow': 'autoCompleteSetup'
},

autoCompleteSetup: function() {
    var self = this;
    this.options = {minLength: 0, source: this.collection.toJSON()};
    this.region_input.autocomplete(self.options);
    this.region_input.autocomplete('search', '');
    this.region_input.autocomplete({
        select: function(event, ui) {
            self.winery_input.val('Search By Winery Name');
            self.findWineries(ui.item.label);   
        } 
    });
},

findWineries: function(label) {
    var newRegionWineriesList = new RegionWineriesList();
    newRegionWineriesList.fetch({
        data: {region: label}, 
        reset: true
    });
}

});

This is also working in that it fetches the new data from the server.

I can't seem to figure out how to update the view once the new data is retrieved. I tried to bind the collection view to the collection but nothing is happening.

Here's the model, collection and collection view. I am leaving out the model view. Please advise if I need that and I will edit.

var RegionWinery = Backbone.Model.extend();

var RegionWineriesList = Backbone.Collection.extend({

    model: RegionWinery,
    url: '/regions/regions_wineries.json',
    parse: function(response){
        return response.wineries;
    }

});

var RegionWineriesListView = Backbone.View.extend({

    className: 'wineries',

    initialize: function(options) {
        _.bindAll(this, 'render');
        this.listenTo(this.collection, 'reset', this.render);
        this.map = options.map;
        this.render();
    },

    render: function() {
        this.collection.each(function(winery) {
            var marker_view = new MapMarkerView({model: winery, map: this.map });
            var regionWineriesView = new RegionWineriesView({model: winery, marker_view: marker_view});
            this.$el.append(regionWineriesView.render().el);
        }, this);

        return this;
    }

});
Was it helpful?

Solution

Normally the view would look more like this:

var RegionsView = Backbone.View.extend({
    //...
    findWineries: function(label) {
        this.collection.fetch({
            data: {region: label}, 
            reset: true
        });
    }
});

then whatever creates that would create the regional list and whatever else cared would listen to the same collection:

var newRegionWineriesList = new RegionWineriesList();
var v = new RegionsView({ collection: newRegionWineriesList });
someOtherView.listenTo(newRegionWineriesList, 'reset', something_that_handles_the_reset);

A better way would be to set up a global event bus:

window.yourApp = window.yourApp || { };

yourApp.events = _({}).extend(Backbone.Events);

Then whatever it is that wants to know about a region change could listen to the global event bus:

this.listenTo(yourApp.events, 'new-region', function(region) {
    // deal with the new region, this would usually be a method
});

and your RegionsView could broadcast the new region with a trigger call:

this.region_input.autocomplete({
    select: function(event, ui) {
        self.winery_input.val('Search By Winery Name');
        yourApp.events.trigger('new-region', ui.item.label);
    } 
});

One nice advantage of this approach is that it is easy to have several things listening for the region change without having to tightly couple everything.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top