将服务器viewmodel投射到客户端的最佳方法-淘汰赛 [英] Best way to cast server viewmodel to client's - Knockout

查看:94
本文介绍了将服务器viewmodel投射到客户端的最佳方法-淘汰赛的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找将我的服务器模型映射到淘汰视图模型中的最佳方法 为此,我在使用映射插件,

I'm looking the best way to get my server model mapped into the knockout viewmodel for this purpose here I'm using the mapping plugin,

Id,标题,人物被映射到类似于我在此处的groupViewModel的内容, 如何确定并强制将此映射始终准确地投射到新的groupViewModel上,真正的问题是 Id,Title,People 绑定到视图,而不是 addPerson 方法, 请分享关于此问题的最佳解决方法,或者您知道的使其更精确,更简单,更干净的映射方法,谢谢.

Id, Title, People were mapped to something similar to the groupViewModel I have here, How can I be sure and force this mapping to always be casted exactly to a new groupViewModel, the real issue here is Id, Title, People are bound to the view, not the addPerson method, Please share the best workaround on this, or any better way you know to make it thiis mapping precise and yet simple and clean, thanks.

这里的viewModel包含Groups Array,如何将Groups数组转换为GroupViewModel项目,也许可以用这种方式回答问题.

here our viewModel contains Groups Array, how to cast this Groups array into GroupViewModel items , maybe the question could be answered this way.

var model = @Html.Raw(Json.Encode(Model));

$(function() {

    var root = this;
    var viewModel = ko.mapping.fromJS(model, root);
    // there are Groups as expected but not the addPerson
    // will cause undefined exception

    var groupViewModel = function (item) {
        var self = this;
        self.Id = ko.observable(item.Id);
        self.Title = ko.observable(item.Title);
        self.People = ko.observableArray([]);
        self.addPerson = function (name) {
            console.log('addPerson Clicked');
        }; // .bind(self)
    }
    ko.mapping.fromJS(viewModel);
    ko.applyBindings(viewModel);
});     

编辑-根据答案进行了更新:

Edit - Updated based to the answer :

服务器ViewModel

In Server we have this :

    class ServerVm {
        public int Id { get; set; }
        public IList<GroupMap> Groups { get; set; } // groupViewModel
}

在客户中,我们有:

var model = @Html.Raw(Json.Encode(Model));

$(function() {

    var root = this;
    var viewModel = ko.mapping.fromJS(model, root);

    //viewModel.Groups = ko.observableArray([]);
    // No need because it's same as server model

    viewModel.addGroup = function (teamName) {
            console.log('addGroup Clicked');
    }; // .bind(self)       
    // addGroup is fine
    // it's defined here and working fine, no special mapping needed here

    // "model" contains something
    var groupViewModel = function (item) {
        var self = this;
        self.Id = ko.observable(item.Id);
        self.Title = ko.observable(item.Title);
        self.People = ko.observableArray([]);
        // self.addPerson - this is hidden in the "model"
        self.addPerson = function (name) {
            console.log('addPerson Clicked');
        }; // .bind(self)
    }
    ko.mapping.fromJS(viewModel);
    ko.applyBindings(viewModel);
});     

我们的问题是位于嵌套集合内的self.addPerson,这是因为container(groupViewModel)没有自动绑定到GroupMap.每次我手动创建groupViewModel都是可以的,因为我自己进行了转换,但这不是真正的映射解决方案,您的呢,谢谢

Our problem is the self.addPerson located inside our nested collection which because the container(groupViewModel) isn't bound automatically to the GroupMap. everytime I create groupViewModel by hand it's ok cause I'm casting it myself, but this is not the real mapping solution, what's yours, thanks

推荐答案

您可以使用ko.mapping.fromJS方法的不同重载,该方法带有3个参数,来自

You could use different overload of ko.mapping.fromJS method that takes 3 parameters, from documentation:

指定更新目标
... ko.mapping.fromJS的第三个参数指示目标.
ko.mapping.fromJS(data,{},someObject);

Specifying the update target
...The third parameter to ko.mapping.fromJS indicates the target.
ko.mapping.fromJS(data, {}, someObject);

因此,您可以按照以下方式更新视图模型定义:

So in your case you could update your view model definition as follows:

function ViewModel() {
    var self = this;    
    this.addPerson = function(data) {
        $.ajax({
            url: ...+ self.Id,
            contentType: 'application/json;charset=utf-8',
            dataType: 'JSON',
            type: "POST",
            success: function (result) // result
            {
                console.log('Success');
                var avm = new childViewModel(result,self); // another defined vm
                self.People.push(avm);
            }
        });
    }
}
ViewModel.prototype.init = function(data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);
}

并初始化它:

...
var model = @Html.Raw(Json.Encode(Model));
...
var vm = new ViewModel();
vm.init(model);
ko.applyBindings(vm);

请参见演示.

另一种方法(更短一点)是先映射模型,然后向其添加方法,如下所示:

Another approach, a bit shorter, is to map your model first and then add methods to it, like this:

var vm = ko.mapping.fromJS(model);
vm.addPerson = function(data) {
...

查看其他演示.

我更喜欢第一种方法,因为函数是在视图模型内部定义的,以后不再添加.

I like first approach more since function is defined inside view model and not added later.

更新:

因此,在注释中进行了一些澄清之后,以及在更新了问题之后,应该执行以下操作:

So, after some clarification in comments and after question update, here is what should be done:

  1. 您应该在该子对象中使用提到的ko.mapping.fromJS方法来自动映射其属性.
  2. 您应该使用映射对象来告诉mapping插件如何映射您的子对象.
  1. You should use mentioned ko.mapping.fromJS method inside that child object to map it's properties automatically.
  2. You should use mapping object to tell the mapping plugin how to map your child object.

子对象视图模型:

function groupViewModel(data) {
    var self = this;
    ko.mapping.fromJS(data, {}, self);
    self.addPerson = function(personData) {
        // here should be your ajax request, I'll use dummy data again        
    };    
}

映射对象:

var mapping = {
    "Groups" : {
        'create': function(options) {
            return new groupViewModel(options.data);
        }
    }
};

初始化:

var vm = ko.mapping.fromJS(model, mapping);

此处已更新演示.

这篇关于将服务器viewmodel投射到客户端的最佳方法-淘汰赛的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆