我正在寻找将我的服务器模型映射到knockout viewmodel的最佳方法 为此,我在这里使用映射插件
Id,Title,People被映射到类似于我在这里的groupViewModel的东西, 我如何确定并强制将此映射始终精确地投射到新的groupViewModel,这里真正的问题是 Id,Title,People 绑定到视图,而不是 addPerson 方法, 请分享关于此的最佳解决方法,或者您知道的任何更好的方法,使其精确,简单,干净,感谢。
这里我们的viewModel包含Groups Array,如何将这个Groups数组转换为GroupViewModel项,也许问题可以用这种方式回答。
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);
});
编辑 - 根据答案更新:
服务器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
,因为容器(groupViewModel)不会自动绑定到GroupMap。我每次手动创建groupViewModel都可以,因为我自己投了它,但这不是真正的映射解决方案,你的是什么,谢谢
答案 0 :(得分:1)
您可以使用来自documentation的3个参数的ko.mapping.fromJS
方法的不同重载:
指定更新目标
... ko.mapping.fromJS的第三个参数表示目标 ko.mapping.fromJS(data,{},someObject);
因此,在您的情况下,您可以按如下方式更新视图模型定义:
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);
见工作demo。
另一种缩短的方法是首先映射模型然后再添加方法,如下所示:
var vm = ko.mapping.fromJS(model);
vm.addPerson = function(data) {
...
查看另一个demo。
我喜欢第一种方法,因为函数是在视图模型中定义的,后来没有添加。
<强>更新强>
因此,经过评论和问题更新后的一些澄清,以下是应该做的事情:
ko.mapping.fromJS
方法自动映射它的属性。mapping
插件如何映射您的子对象。子对象视图模型:
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);
此处已更新demo。