Converting JSON data to a base model with a child collection
I am working with a Playlist object that has some properties defining itself as well as a PlaylistItem collection.
When I receive data from my server, I receive a JSON response in my client side success method:
success: function (data) {
console.log("JSON data:", data);
playlists = _.map(data, function (playlistConfig) {
return new Playlist(playlistConfig);
});
...
}
Here I am converting JSON data to Playlist objects. Each Playlist object is a .Model base.
This is what my data looks like:
And this is what the playlist constructor looks like:
return function(config) {
var playlist = new Playlist(config);
return playlist;
};
var Playlist = Backbone.Model.extend({
defaults: function() {
return {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: Backbone.Collection.extend({
model: PlaylistItem
})
};
},
...
}
My problem:
If I create a Playlist object with default values, it is initialized with an empty Backbone.Collection for the PlaylistItem. However, if I create a Playlist object with a collection already defined, I get the underlying array and not the Backbone.Collection. This is because I am working with JSON data from a server that has not yet been converted to Backbone objects. This data propagates to the playlist defaults and overwrites the Backbone.Collection object.
What is the correct way to initialize with a filled Backbone.Collection? I could write code in Initializes that checks the type of my items array and if it is not Backbone.Collection I could create a new Backbone.Collection and add items to it and then replace the old array with a new one, but that seems really hoakey ...
source to share
Don't define your PlalistItems collection inside default values, but in advance. Then create an initialization method in your playlist model, for example:
var PlaylistItems = Backbone.Collection.extend({
...
});
var Playlist = Backbone.Model.extend({
initialize: function() {
this.set('items', new PlaylistItems(this.items));
},
defaults: function() {
return {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: [] // don't define your PlaylistItems Collection here
};
}
});
Have a look at the fiddle here: http://jsfiddle.net/georgedyer/r2XKb/ (you need to open your console to see the collection)
source to share
Another problem I ran into was that after saving your model to the server, you get a response that will change your inline collection into a regular javascript array. To fix this, I had to override the parsing function in my model class as follows:
var model = backbone.Model.extend({
urlRoot : "/rest/model",
initialize: function(){
this.set("myCollection", new MyCollection(this.myArray));
},
defaults: {
myArray: []
},
parse: function(response){
this.set(response);
this.set("myArray", new MyCollection(response.myArray));
}
});
source to share