In my project, I use Backbone collection to arrange the application's data and I also need to sync my data to localstorage. My data is a two level deep nested collections and models, and there is where the problem happens.
After the inner collection synchronizes to localstorage, it becomes a raw array of objects. So the collection method (like add
) can not be used.
After debugging and googling, I found the reason:
When localStorage serializes the model, it calls model.toJSON()
, and it simply clones the model's attributes, excluding the nested collection.
// Return a copy of the model's `attributes` object.
toJSON: function(options) {
return _.clone(this.attributes);
},
so it uses Underscore's clone function, and the doc says that it:
Create a shallow-copied clone of the provided plain object. Any nested objects or arrays will be copied by reference, not duplicated.
So I am searching a deep copy method to override the default model's .toJSON
. But I can't figure out the correct way.
For example, I tried the following:
Backbone.Model.prototype.toJSON = function() {
var json = $.extend(true, {}, this.attributes);
return json;
};
Edit, based on the Emile's suggestion, My real Model goes as following:
app.RecordItem = Backbone.Model.extend({
defaults: {
target: 1,
date: '',
day: '',
//foodlist: new TrackList(),
currentvalue: 0,
isSetup: false,
},
initialize: function() {
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var d = new Date();
this.set("date", d.getDate() + "." + months[d.getMonth()]);
this.set("day", days[d.getDay()]);
//
var foodlist = this.getFoodlist();
if (!(foodlist instanceof TrackList)) {
this.set('foodlist', new TrackList(foodlist));
}
},
getFoodlist: function() {
if (!this.foodlist) this.foodlist = new TrackList(this.get('foodlist'));
return this.get('foodlist');
},
toJSON: function(options) {
// this gets the default behavior
var attrs = this.constructor.__super__.toJSON.apply(this, arguments);
var foodlist = attrs.foodlist;
if (foodlist) {
// then replace the collection reference with the actual serialized data
attrs.foodlist = foodlist.toJSON(options);
}
return attrs;
},
});
After override the toJSON
method. The error message is
"foodlist.toJSON is not a function(…)"