I am trying to solve a small problem with ko mapping. The scenario is that my ViewModel is basically a collection of objects. Each of the objects is created from a json call, in this way:
var ViewModel = ko.observableArray();
$.getJSON(url, function(data) {
ViewModel.push(ko.mapping.fromJSON(data));
});
This works perfectly and I can do all sort of magic in my HTML. The question is if for example I want to add something to my collection, let's say to support client-side "Add and Edit" scenario. I would like to do something like:
<input type="button" value="add new" data-bind="click: AddNew" />
And I would like the AddNew function in the ViewModel to be something like:
function AddNew() {
this.push(// WHAT HERE?);
}
Basically I need to push an object which is identical to the other already existing, but of course with all blanked out properties...
I was thinking of a way of "cloning" an object form the list and setting all the observables to empty but I would not know where to start I'm afraid :/
If you are going to expand your functionality to client-side edit/add then i would recommend formalizing your objects into a js class and then mapping these objects internally. This would allow you to have your add methods on your main viewmodel and create blank instances client side easily.
One caveat with the mapping plugin is that for updating objects it expects those objects to have been originally mapped by the plugin. Here's a quick example of how it could be done.
var YourObjectClass = function (config) {
var self = this, data;
// your default structure goes here
data = $.extend({
name: "",
id : -1
}, config);
ko.mapping.fromJS(data, {}, self);
};
var viewModel = function(initialData) {
var self = this;
ko.mapping.fromJS(initialData, {
items: {
create : function (options) {
return new YourObjectClass(options.data);
}
}
}, self);
this.AddNew = function () {
self.items.push(new YourObjectClass());
}
};
Hope this helps.