我最近开始使用 Knockout,大多数事情都非常容易。然而,这个让我有点难过,希望有人能提供一些帮助。我正在通过序列化具有 Master/Detail 结构的 JSON 对象来创建我的 Knockout 模型,我怀疑这会导致我的一些问题。我可以绑定/呈现记录的主部分,并且可以使用 foreach 模板绑定和呈现详细信息。但是,在我的场景中,我希望用户从子列表中选择要编辑的详细记录。问题是我无法让选择起作用。我正在触发 click 事件,并且似乎我的详细记录正在传递给我的事件 - 除了我无法读取属性的值。在提琴手看来,通过的对象是事件的函数调用。目前还不确定。所以,这是我的设置
我的 JSON
{
"Height":"250",
"Width":"200",
"Speed":"700",
"Pause":"4",
"ShowItems":"1",
"Animation":"fade",
"MousePause":"true",
"IsPaused":"false",
"Direction":"up",
"DataItems":[{
"OrderId":1,
"ItemHtml":"This is item 1"
},{
"OrderId":2,
"ItemHtml":"This is item 2"
},{"
OrderId":3,
"ItemHtml":"This is item 3"
}]
}
用于序列化 JSON 对象的 Javascript
var viewModel = {
vmRotator: ko.mapping.fromJSON(jsonObj)
//-- THIS IS WHERE I THINK THE PROBLEM IS
, selectRotatorItem: function (item) {
//alert(item.OrderId); // THIS DOES NOT WORK
console.log(item);
}
}
ko.applyBindings(viewModel);
//-- hookup the click event for templated items
$("#rotatorItems").on("click", ".sel", function () {
var data = ko.dataFor(this);
viewModel.selectRotatorItem(data); //-- call to object function
});
用于显示项目的 HTML,提供单击按钮
<table id="rotatorList" width="100%" border="0" cellspacing="0" cellpadding="2">
<tbody id="rotatorItems" data-bind="template: { foreach: vmRotator.DataItems }">
<tr>
<td style="width: 20px;">
<input type="button" class="sel" value="Select" />
<span data-bind="text: OrderId"></span>
</td>
<td style="width: 90%;" data-bind="text: ItemHtml"></td>
</tr>
</tbody>
</table>
最好我能说这一切正常。我的事件正在被调用,但是当我在控制台中查看结果时,它看起来像是函数的文本而不是值。
在函数中:
, selectRotatorItem: function (item) {
//alert(item.OrderId); // THIS DOES NOT WORK
console.log(item);
}
alert(item.OrderId) 显示:
"function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Wa(d);return c}"
而不是像 1 或 2 这样的数字,它是 Order ID 的值。不知道为什么会这样,但我做错了什么。
我通过查看几个与我正在做的类似的示例将这段代码拼凑在一起。我可能会以完全错误的方式解决这个问题,但我认为我只是缺少一些简单的东西。我敢肯定,那里的一些 Javasctipt 神可以很容易地看到我看不到的东西,所以我很感激你的帮助。
为了回应符文对我最初问题的回答,这是有效的最终版本
用于构建绑定的 Javascript 代码
//-- define models: master and detail modesl
var viewRotatorItemModel = {
'Height': ko.observable(),
'Width': ko.observable()
};
var viewRotatorModel = {
'Height': ko.observable(),
'Width': ko.observable(),
'Speed': ko.observable(),
'ShowItems': ko.observable(),
'Animation': ko.observable(),
'IsPaused': ko.observable(),
'Direction': ko.observable(),
'UseEditor': ko.observable(),
'HtmlData': ko.observable(),
'DataItems': {
create: function (options) {
return new viewRotatorDataItem(options.data);
}
}
};
//-- define objects around models
var viewRotatorDataItem = function (data) {
var self = this;
//--> IMPORTANT TO USE fromJS as JSON is already an object
ko.mapping.fromJS(data, viewRotatorItemModel, self);
self.selectItem = function () {
alert("item with id " + self.OrderId() + " clicked");
};
};
var ViewModel = function (data) {
var self = this;
//--> IMPORTANT TO USE fromJSON as incoming object is JSON text
ko.mapping.fromJSON(data, viewRotatorModel, self);
};
...
...
//-- create objects when ready
vmRotator = new ViewModel(jsonObj);
ko.applyBindings(vmRotator);
用于显示主/明细项目的 HTML
<h4>Main Items</h4>
<input type="text" id="wc_Height" data-bind="value: vmRotator.Height" />
<input type="text" id="wc_Width" data-bind="value: vmRotator.Width" />
<h3>Detail Items</h3>
<table id="rotatorList" width="100%" border="0" cellspacing="0" cellpadding="2">
<tbody id="rotatorItems" data-bind="template: { foreach: vmRotator.DataItems }">
<tr>
<td style="width: 20px;">
<input type="button" value="Select" data-bind="click: selectItem" />
<span data-bind="text: OrderId"></span>
</td>
<td style="width: 90%;" data-bind="text: ItemHtml"></td>
</tr>
</tbody>
</table>