Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

backbone fetch collection on page load

i know that backbone doc says fetch should not be used to populate collections on page load,and i kind of figure out why:

var appCollection = Backbone.Collection.extend({
    model:appModel,
    url:'api/app',
    initialize:function(){
        this.fetch();
    },

});

var homeView = Backbone.View.extend({
    el:'#content',
    initialize:function(){
        this.collection = new appCollection(appModel)
        this.render()   

    },
    render: function () {
        var that = this;
        alert(1);
        _.each(this.collection.models, function (item) {
            that.renderApp(item);
         }, this);


    },

    renderApp: function (item) {
        var appview = new appView({
            model: item
        });

        this.$el.append(appview.render().el);
    }
})
 var home = new homeView();

the homeview.render function actually get called before the collection fetched, so when i remove the alert(1); my app wont get rendered, and i get some error says "appname"(template) is undefined.

any idea how to do this?

the fetch method comes really handy and i dont mind to wait for a few second,actually i was intend to show a progress bar indicating that the page is initializing because i got lots of other thing to download,so is it possible to use fetch and when the collection is actually fetched then tha code continue to run???

like image 805
paynestrike Avatar asked Dec 12 '22 23:12

paynestrike


1 Answers

Let's take this from the beginning:

var appCollection = Backbone.Collection.extend({
    model:appModel,
    url:'api/app',
    initialize:function(){
        this.fetch();
    },

});

I would avoid fetching inside initialize. Creating an instance of an appCollection should not necessitate fetching. So use:

var appCollection = Backbone.Collection.extend({
    model:appModel,
    url:'api/app',    
});

Then,

var homeView = Backbone.View.extend({
    el:'#content',
    initialize:function(){
        this.collection = new appCollection(appModel)
        this.render()   

    },
    render: function () {
        var that = this, p;
        console.log('fetching...');
        p = this.collection.fetch();
        p.done(function () {
            console.log('fetched!');
            _.each(that.collection.models, function (item) {
                that.renderApp(item);
            }, that);
        });
    },

    renderApp: function (item) {
        var appview = new appView({
            model: item
        });

        this.$el.append(appview.render().el);
    }
})
var home = new homeView();

This allows you to render your homeView and when the collection has been fetched, it will render its models. If you do not understand what p.done does, have a look at jQuery's Deferred. In brief an ajax request returns a promise. When the promise is fulfilled (i.e. your collection is fetched) the deferred fires and whatever function you specified in .done() will execute. Use the points where I console.log to give feedback on the progress.

like image 187
ggozad Avatar answered Jan 01 '23 10:01

ggozad