Collection of Backbone.Js with specific types.

I have a BackboneJS collection called History that can contain one of several Backbone JS models (which extend from HistoryItem that extends from Backbone.Model), I'm trying to find a way to restore this on boot, unfortunately it seems that the BackboneJS collection may specify only a specific model, for example

HistoryCollection = Backbone.Model.extend({ model: app.models.HistoryItem }) 

What I really need to do is define this for each type, this is what I would like to do

  HistoryCollection = Backbone.Model.extend({ model: function(item) { return app.models[item.type]; } }) 

Any ideas before I work with the poppy to implement this? (i.e., an attribute of a collection model that can accept a function)

+6
source share
3 answers

Playing firebug .. came up with an approach where you can override the collection parsing method instead of specifying a model. Your parsing implementation basically becomes a simple factory to populate the collection with the models you want:

 var BaseModel = Backbone.Model.extend({ meth: function(){ return 'Base method'; }, }); var SubModel = BaseModel.extend({ meth: function(){ return 'Sub1 method'; } }); var SubModel2 = BaseModel.extend({ meth: function(){ return 'Sub2 method'; } }); var ModelCollection = Backbone.Collection.extend({ parse: function(data){ var self = this; data.forEach(function(item){ switch(item.type){ case 1: self.add(new SubModel(data)); break; case 2: self.add(new SubModel2(data)); break; default: self.add(new BaseModel(data)) } }); } }); //Example Use x = new ModelCollection; x.parse([{type: 1},{type: 2}, {type: 99}]); x.map(function(e){ return e.meth();}); 
+7
source

IMHO, I prefer playing with the model method in the collection:

 var MyCollection = Backbone.Collection.extend({ model : function(attrs, options){ switch (attrs.type) { case 1 : model = new ModelType1(attrs, options); break; case 2 : model = new ModelType2(attrs, options); break; default : model = new BaseModel(attrs, options); break; } } }); 

or using the proxy model:

 ProxyModel = Backbone.Model.extend({ initialize: function() { switch (this.get('type')) { case 1 : model = new ModelType1(attrs, options); break; case 2 : model = new ModelType2(attrs, options); break; default : model = new BaseModel(attrs, options); break; } return new model; } }) var MyCollection = Backbone.Collection.extend({ model : ProxyModel, }); 
+4
source

I just implemented this feature and started with the advice of Jake Dempsey, however you really need to override another method in the collection. This is the code I used:

 var MyCollection = Backbone.Collection.extend({ _prepareModel: function(model, options) { if (!(model instanceof Backbone.Model)) { var attrs = model; switch (attrs.type) { case 1 : model = new ModelType1(attrs, { collection: this }); break; case 2 : model = new ModelType2(attrs, { collection: this }); break; default : model = new BaseModel(attrs, { collection: this }); break; } if (model.validate && !model._performValidation(attrs, options)) model = false; } else if (!model.collection) { model.collection = this; } return model; } }); 

Note that this is a private (ish) method, so something needs to be kept in mind when upgrading Backbone.

0
source

Source: https://habr.com/ru/post/888558/


All Articles