When is the right time to fetch a collection in Backbone js?

backbone-views, backbone.js

Solution

The problem in your code is that your `campaignListView` fetch the collection when it is initialized and it is initialized only once. Your `render` method which is actually called from the router doesn't call your `initialize` method of campaignListView, when you change the`url` your second time.

You have two options here :

1. return the class not the instance of your campaignListView and initialize it in the router :

// in your router code
showCampaigns: function(){
    var campaignListViewInstance = new campaignListView(); // don't forget the brackets after your initialize function
    campaignListViewInstance.render();
},

// in your campaignListView code :
return campaignListView; // without "new"

This will initialize the code everytime the router is hit.

2. place your fetch in the render method

// in your campaignListView code :
initialize:function(){
    this.collection = campaignsCollection;
},
render: function(){
    this.collection.fetch({success: function(collection) {
        var data = {
            campaigns: collection,
            _: _
        };
        $('#container').html('Campaigns length: '+data.campaigns.models.length);
    }); // this will be fetched everytime you render and also it has success callback
}

Also be aware that you should replace all your instance creating functions with brackets at the end

return new campaignListView; --> return new campaignListView();
return new campaignsCollection; --> return new campaignsCollection();

Another problem you will face is the async work of `fetch`. You should use success or event driven rendering of your collection, because `fetch` works in the background and you will have no data when you immediately call render after calling `fetch`.

+1 for your AMD approach.

Problem

So I'm working on a backbone app, and trying to modularize things as much as I can using require.js. This has been my guide. I'm having trouble getting my view to always fetch my collection. If I access my app from the base url (`myapp.com/`), and go to the route of my view, the collection is fetched. If I do not go to the view, and instead access it from `myapp.com/#/campaigns`, then the collection is not fetched. Here is some relevant code. router.js ``` define([ 'jQuery', 'Underscore', 'Backbone', 'views/home/main', 'views/campaigns/list' ], function($, _, Backbone, mainHomeView, campaignListView ){ var AppRouter = Backbone.Router.extend({ routes: { // Define some URL routes 'campaigns': 'showCampaigns', // Default '*actions': 'defaultAction' }, showCampaigns: function(){ campaignListView.render(); }, defaultAction: function(actions){ // We have no matching route, lets display the home page //mainHomeView.render(); } }); var initialize = function(){ var app_router = new AppRouter; Backbone.history.start(); }; return { initialize: initialize }; }); ``` collections/campaigns.js ``` define([ 'jQuery', 'Underscore', 'Backbone', 'models/campaigns' ], function($, _, Backbone, campaignsModel){ var campaignsCollection = Backbone.Collection.extend({ model: campaignsModel, url: '/campaigns', initialize: function(){ } }); return new campaignsCollection; }); ``` views/campaigns/list.js ``` define([ 'jQuery', 'Underscore', 'Backbone', 'collections/campaigns' ], function($, _, Backbone, campaignsCollection){ var campaignListView = Backbone.View.extend({ el:$('#container'), initialize:function(){ this.collection = campaignsCollection; this.collection.fetch(); }, render: function(){ var data = { campaigns: this.collection, _: _ }; $('#container').html('Campaigns length: '+data.campaigns.models.length); } }); return new campaignListView; }); ``` Any ideas on what I'm doing wrong? I believe it has something to do with calling `this.collection.fetch()` in the `initalize` function of the view. If that is the issue, where should I put `fetch()`?

Original source