Question

Basically, I'm trying to send a GET request to my Node server, so that I can get back blog posts to create links. I do a collection.fetch, which successful completes the GET request (the Node server logs that it's sending the right objects). The model successfully parses the right data, but when I try to use the collection, it says that it's empty. Here's the code:

var mdm = mdm || {};

// MODEL
mdm.Post = Backbone.Model.extend({
        parse: function( response ) {
        response.id = response._id;
        console.log(response); // logs the two documents
        return response;
    }
});

// COLLECTION
mdm.Posts = Backbone.Collection.extend({
    model: mdm.Post,
    url: '/api/posts'
});

// MODEL VIEW
mdm.LinkView = Backbone.View.extend({
    template: _.template( $('#link_template').html() ),

    render: function() {
        this.$el.html( this.template( this.model.toJSON() ));
        return this;
    }
});

// COLLECTION VIEW
mdm.LinksView = Backbone.View.extend({
    el: '#link_list',

    initialize: function() {
        this.collection = new mdm.Posts();
        this.collection.fetch({reset: true});
                // makes the request properly, but collection is empty
        this.render();
                // never gets called because the collection is empty
        console.log(this.collection.length); 
                // logs a length of 0
    },

    render: function() {
        // renders collection
    }
});

$(function() {
    new mdm.LinksView();
});

The data is being sent and is parsed in the models, so I'm not sure what the collection ends up being empty. Any help would be greatly appreciated.

Was it helpful?

Solution

The most likely reason you are not seeing the models in your view is because the render is happening before the asynchronous fetch is complete.

Something like below would work better:

mdm.LinksView = Backbone.View.extend({
    el: '#link_list',

initialize: function() {
    this.collection = new mdm.Posts();
    this.listenTo(this.collection, 'reset', this.render);
    this.collection.fetch({reset: true});
}

The above code sets a listener for the reset event on the collection and executes the render function when that happens.

Also, you could passing in success and error handlers into fetch and call the render function manually as well.

this.collection.fetch({
    success: _.bind(function() { 
        this.render(); }, this)
});

Hope this helps!

OTHER TIPS

Per @fbynite's comment, the problem was related to fetch being asynchronous. I made the following changes to the collection view, and it did the trick:

initialize: function() {
    var self = this;
    this.collection = new mdm.Posts();
    this.collection.fetch({reset: true,
        success: function() {
            self.render();
            console.log(self.collection.length);
        }
    });
},

The code is a modification from a Backbone tutorial, so other users may encounter a similar problem. http://addyosmani.github.io/backbone-fundamentals/#exercise-2-book-library---your-first-restful-backbone.js-app

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