现在,我正在将这个JSON与KO Mapping插件一起使用,它运行良好:
{
"Controls": [
{
"Fields": [
{
"Name": "emailField",
"Text": "email",
"Visible": true
},
{
"Name": "hiddenField",
"Text": "text",
"Visible": true
}
],
"Name": "form2",
"Type": "Form"
},
{
"Data": [
[
"Federico Aloi",
20
],
[
"Andres Lopez",
31
],
[
"Pablo Perez",
32
]
],
"Fields": [
{
"Name": "nameField",
"Text": "Nombre",
"Visible": true
},
{
"Name": "ageField",
"Text": "Edad",
"Visible": true
}
],
"Name": "datagrid1",
"Type": "Datagrid"
}
],
"Name": "pagina1",
"Title": "Probando el KO"
}
现在我的要求是执行“部分更新”。有些情况我想这样做:
也许另一种解决方法是使用ko.mapping.toJS(viewModel)
重新创建原始对象,更改它然后再重新映射...但我相信你会得到更好的东西。
编辑:我尝试使用ko.mapping.fromJS(updatedControl, viewModel.Controls()[0])
,但它没有用,这是我的代码:
function (control) {
$.getJSON($.format('api/control/{0}/{1}', viewModel.Name(), control.Name()), function (response) {
ko.mapping.fromJS(response, viewModel.Controls()[0]);
});
},
响应:的
{
"Fields": [
{
"Name": "emailField",
"Text": "email",
"Visible": true
},
{
"Name": "hiddenField",
"Text": "text",
"Visible": true
}
],
"Name": "form2",
"Type": "Form"
}
查看
答案 0 :(得分:6)
我认为这是映射插件中最受欢迎的问题。该插件目前只能对属性进行部分更新。例如,如果您要将以下数据重新映射到您的对象
{ "Name": "pagina1 foo", "Title": "Probando el KO bar" }
它只会更新这些属性。但是,如果您使用以下内容重新映射,则对集合进行不同的处理。
{ "Name": "pagina1 foo", "Title": "Probando el KO bar",
Controls: [ { // snip some updated object } ] }
它将删除Controls集合中的不匹配项,而不是更新匹配项。实现此功能的唯一方法是遍历集合并映射您要更新的每个项目。您的代码几乎在正确的轨道上我相信它应该是
ko.mapping.fromJS(updatedControl, viewModel.Controls()[0])
修改强>
你错过了fromJS调用的中间映射参数。
映射对象通常是可选的,但我想如果你像你的情况一样映射一个子对象,插件就不能告诉这个子项父对象最初是没有选项映射的。
希望这有帮助。
答案 1 :(得分:0)
我认为这就是拥有“关键”的重点。选项。我意识到这种功能有一些警告,但我很惊讶那里根本没有支持它。
无论如何 - 这是(遗憾的是)我最终必须做的部分更新订单清单 - 这是循环和替换项目。
data
是来自服务器的主要AJAX / JSON模型,包含data.orders
ko.observableArray([])
个OrderViewModel
个项目。它还包含我想要初始映射的所有其他内容data.products
,data.foo
。
我有一个映射规则,可以在映射过程中自动创建新的OrderViewModel
对象。
var mapping =
{
'orders':
{
key: function (item)
{
return ko.utils.unwrapObservable(item.orderId);
},
create: function (options)
{
return new OrderViewModel(options.data);
}
}
};
当我从服务器获取数据时,我最初想要对我的模型进行完整的映射。所以我设置了initialUpdate=true
。
当我想刷新单个订单时,我有initialUpdate=false
。
if (initialUpdate)
{
// standard initial mapping
ko.mapping.fromJS(data, mapping, this);
}
else
{
// merge orders
var newModel = ko.mapping.fromJS(data, mapping);
// go through all orders in the updated list
for (var i = 0; i < newModel.orders().length; i++)
{
var newOrder = newModel.orders()[i];
// find order with same key in existing ko model
var match = ko.utils.arrayFirst(this.orders(), function (item)
{
return newOrder.orderId() === item.orderId();
});
if (match == null)
{
// TODO: insert new order
}
// replace original order in list
this.orders.replace(match, newOrder);
}
}