Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a collection with several model types in backbone.js?

I'm trying to get this to work but I struggle with it. My Collection ends up empty when I check the success callback on fetch. It doesn't give me any clear errors thou during parse. Here's my code:

My collection:

VOR.Collections.GridItems = Backbone.Collection.extend({
        model : VOR.Models.GridItem,
        url: "assets/data/grid.json",
        parse: function(response){
            var self = this;

            _.each(response, function(griditem){
                switch(griditem.type){
                    case "news":
                        self.add(new VOR.Models.NewsGridItem(griditem));
                        break;
                    default:
                        self.add(new VOR.Models.StandardGridItem(griditem));
                        break;
                }
            });
        }
});

This is how I create the collection:

griditems = new VOR.Collections.GridItems();

griditems.fetch({
    error: function(e) {console.log(e);},
    success: function(msg) {
        console.log(msg)
    });

When I console log msg I get: Object { length=0, models=[0], _byId={...}, more...}

I've also logged the parse function in the collection and it runs thru the JSON file just fine...any ideas on what could be wrong here? The length of the msg object should be 5..i.e. that's how many times the parse function loops and (should) add a model to the collection.

like image 639
Joel Avatar asked Aug 22 '11 11:08

Joel


2 Answers

A nice way of handling this is to redefined the model attribute, which tell the collection how to add a new model to the collection, as explained in this POST : A Backbone.js Collection of multiple Model subclasses (thanks @rulfzid, who answered my question :))

In your case, you should be able to define the model attributes like this :

var VOR.Collections.GridItems = Backbone.Collection.extend({

  url: "assets/data/grid.json",

  model: function(attrs, options) {
    switch(attrs.type) {
      case "news":
        return new VOR.Models.NewsGridItem(attrs, options);
      default:
        return new VOR.Models.StandardGridItem(attrs, options);
    }
  }

});
like image 166
Tricote Avatar answered Oct 06 '22 01:10

Tricote


It will be better to store your grid items in different collections and wrap them with model like this:

var model = Backbone.Model.extend({
    url: 'assets/data/grid.json'
    newsItems: Backbone.Collection.extend({
        model: VOR.Models.NewsGridItem
    }),
    standartItems: Backbone.Collection.extend({
        model: VOR.Models.StandardGridItem
    }),

    initialize: function() {
        this.newsItems = new this.newsItems();
        this.standartItems = new this.standartItems();

        this.newsItems.bind('all', function() {
            this.trigger.apply(this, arguments);
        }, this)
        this.standartItems.bind('all', function() {
            this.trigger.apply(this, arguments);
        }, this)
    },

    parse: function(request) {
        _.each(response, _.bind(function(griditem) {
            switch (griditem.type) {
                case "news":
                    this.newsItems.add(griditem);
                    break;
                default:
                    this.standartItems.add(griditem);
                    break;
            }
        }, this));
    }
})

model.fetch()
like image 28
ant_Ti Avatar answered Oct 06 '22 01:10

ant_Ti