Multiple arrays in one Knockout.JS ViewModel

2019-08-10 07:59发布

I have run into the case where I am having to use multiple ViewModels in the same view. I achieved that by using this kind of trick which allows multiple bindings on different items of the DOM:

ko.applyBindings(supervisors, $('#supervisorContainer')[0]);
ko.applyBindings(permits, $('#permitContainer')[0]);

On previous views, I only had to bind one mini object, like a PeopleModel. Now as other pages are getting more complex, I feel as though the better way to do it would be to encapsulate these smaller models inside of the larger main model as arrays. I haven't seen any examples of this around, so let's say we have a project. In this project there are many supervisors and many permits. Supervisors and permits are observable arrays. Right now I have them each both as their own model, but conceptually it might make more sense for the one and only model to be the ProjectModel, and then to have Supervisors and Permits as arrays inside of that model.

Using an example right from the Knockout.JS website, I don't see how something like this could be converted to be a ProjectModel with multiple arrays inside, mainly because of the language, such as how gifts are passed to the function.

var GiftModel = function(gifts) {
    var self = this;
    self.gifts = ko.observableArray(gifts);

    self.addGift = function() {
        self.gifts.push({
            name: "",
            price: ""
        });
    };

    self.removeGift = function(gift) {
        self.gifts.remove(gift);
    };
};

var viewModel = new GiftModel([
    // Data goes in here 
]);
ko.applyBindings(viewModel);

Is this way of thinking correct? Or is there a better way? The following code does actually seem to work with my foreach loops in the view:

var ProjectModel = function(supervisors, permits) {
    var self = this;
    self.supervisors = ko.observableArray(supervisors);
    self.permits = ko.observableArray(permits);

    self.addPermit = function() {
        self.permits.push({
            number: "",
            date: ""
        });
    };

    self.removePermit = function(permit) {
        self.permits.remove(permit);
    };

    self.addSupervisor = function() {
        self.supervisors.push({
            name: "",
            number: ""
        });
    };

    self.removeSupervisor = function(supervisor) {
        self.supervisors.remove(supervisor);
    };

};

var viewModel = new ProjectModel(supervisorJSONArray,permitJSONArray);
ko.applyBindings(viewModel);

1条回答
对你真心纯属浪费
2楼-- · 2019-08-10 08:29

You've really 'melded' the two viewModels together... instead I would 'composite' them together, something like this:

var PermitsViewModel = function(permits) {
    // Permits functionality and observables here
}
var SupervisorsViewModel = function(supervisors) {
    // Supervisors functionality and observables here
}

var ProjectModel = function(supervisors, permits) {
    var self = this;
    self.supervisorsViewModel = new SupervisorsViewModel(supervisors);
    self.permitsViewModel = new PermitsViewModel(permits);

};

var viewModel = new ProjectModel(supervisorJSONArray,permitJSONArray);
ko.applyBindings(viewModel);

You could then use 'with' statements in the view to reference the appropriate view model.

查看更多
登录 后发表回答