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

I am trying to get this to work, but I am struggling with it. My collection ends up empty when I check the success callback on fetch . This does not give me any obvious errors during parse . Here is 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 consolidating msg log I get: Object {length = 0, models = [0], _byId = {...}, more ...}

I also registered the parse function in the collection and it runs through the JSON file just fine ... any ideas on what might be wrong here? The length of the msg object should be 5..ie that how many times the parse function sings and (should) add the model to the collection.

+7
source share
3 answers

A good way to handle this is to override the model attribute, which tells the collection how to add a new collection to the collection, as explained in this POST: A Backbone.js Collection of several Model subclasses (thanks to @rulfzid who answered my question :) )

In your case, you should define the model attributes as follows:

 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); } } }); 
+18
source

It’s better to store the grid elements in different collections and wrap them using this model:

 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() 
+1
source
 // **parse** converts a response into a list of models to be added to the // collection. The default implementation is just to pass it through. parse : function(resp) { return resp; }, 

This is what the doctor says you should do in parsing. Everything that you return will be set as the initial array of the collection. Here it is called from:

  options.success = function(resp) { collection[options.add ? 'add' : 'refresh'](collection.parse(resp), options); if (success) success(collection, resp); } 

So, I would suggest changing your parsing to:

 return _.map(response, function(griditem){ switch(griditem.type){ case "news": return new VOR.Models.NewsGridItem(griditem); break; default: return new VOR.Models.StandardGridItem(griditem); break; } }); 
0
source

All Articles