JeiKei JeiKei - 5 months ago 16
Javascript Question

Wrong backbone collection length. Can't each this collection

Sorry for my bad English. Tell me why the following happens:

I have some backbone collection:

var Background = window.Models.Background = Backbone.Model.extend({});

var Backgrounds = window.Models.Backgrounds = Backbone.Collection.extend({

model: window.Models.Background,

url: '/backgrounds/',

initialize: function() {

this.fetch({
success: this.fetchSuccess(this),
error: this.fetchError
});
},

fetchSuccess: function( collect_model ) {
new BackgroundsView ({ collection : collect_model });
},

fetchError: function() {
throw new Error("Error fetching backgrounds");
}

});


And some view:

var BackgroundsView = window.Views.BackgroundsView = Backbone.View.extend({

tagName: 'div',

className: 'hor_slider',

initialize: function() {
this.render();
},

render: function() {
console.log(this.collection);
this.collection.each( function (background) {
console.log(background);
//var backgroundView = new BackgroundView ({ model: background });
//this.$el.append(backgroundView.render().el);
});
}

});


now i creating collection

var backgrounds = new Models.Backgrounds();


but when I must render this view, in the process of sorting the collection its length is 0, but should be two. This log I see at console. How is this possible? What am I doing wrong??

T J T J
Answer

You are creating the view before the collection fetch is successfull. Your code should be:

initialize: function() {

    this.fetch({
        success: this.fetchSuccess,
        //------------------------^ do not invoke manually
        error: this.fetchError
    });
},
fetchSuccess: function(collection, response) {
    new BackgroundsView ({ collection : collection});
},

You should let backbone call fetchSuccess when the fetch succeeds. Right now you're invoking the funcion immediately and passing the return value undefined as success callback.


This looks like a wrong pattern. Your data models shouldn't be aware of/controlling the presentation logic.

You have a view floating around without any reference to it. You should be creating a view instance with reference(for example from a router, or whatever is kick starting your application) and passing the collection to it. Then fetch the collection from it's initialize method and render after the fetch succeeds. Collection can be referenced via this.collection inside view.

Alternatively you can fetch the collection from router itself and then create view instance. Either way collection/model shouldn't be controlling views.

Comments