How can I create a typed collection class in Knockout mapping?

混江龙づ霸主 提交于 2019-12-25 00:09:07

问题


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.


回答1:


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

http://jsfiddle.net/xop2go2z/

//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);
    }
};


来源:https://stackoverflow.com/questions/26889139/how-can-i-create-a-typed-collection-class-in-knockout-mapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!