Reputation: 13838
I'm using knockout with the mapping plugin so that I can write code like this:
function ContactViewModel() {
//other properties...
this.emails = ko.observableArray();
}
function ContactEmailViewModel() {
//other properties...
this.address = ko.observable();
}
var koContactMap = {
'emails': {
create: function (options) {
return new ContactEmailViewModel(options.data);
}
}
};
var model = new ContactViewModel();
ko.mapping.fromJS([JSON data from web service], koContactMap, model);
In English, I have contacts
and emails
, and a contact
has emails
.
This works perfectly, and I can load the contact and have the data and emails populated, and the emails are of type ContactEmailViewModel
, as I want.
But the thing I'm confused about is: why does the map create method return a singular email object instead of a collection of email objects. The emails
property is a collection, but seems to be populated by returning a single object, and is called multiple times, once for each member.
This correctly populates the emails
property. But now I want to change emails
from an array to an EmailsList
object, so that I can give it methods, and I can't see how to do this, since the create method returns individual emails, not the whole emails property.
Upvotes: 0
Views: 83
Reputation: 17554
For that behaviour you can add ignore
on the emails propery and let the mapping plugin serperate map the emails into a standar array that you feed the EmailsList constructor with.
var emailMapping = {
create: function(opt) {
return new Email(opt.data);
}
};
this.emails = new EmailList(ko.mapping.fromJS(arr, emailMapping));
Hmm, you could also extend a custom class with a observableArray I think (havent tested) that ko.mapping will then just add emails to your EmailList like
this.emails = new EmailList(); //This is is a ko.observableArray the mapping plugin will populate it with emails
ko.mapping.fromJS(data, mappingInfo, this);
https://github.com/knockout/knockout/blob/master/src/subscribables/observableArray.js
update: I just confirmed that solution two worked, so I would say thats a good way of doing it
//stolen from ko source
function setPrototypeOf(obj, proto) {
obj.__proto__ = proto;
return obj;
}
ko.MyList = function(arr) {
var result = ko.observableArray(arr);
return setPrototypeOf(result, ko.MyList.fn);
}
ko.MyList.fn = {
pushMyThingy: function(obj) {
this.push(obj);
}
};
Upvotes: 1