我最近开始与Knockout合作,大多数事情都很容易。然而,这个让我有点难过,并希望有人可以提供一些帮助。我通过序列化具有Master / Detail结构的JSON对象来创建我的Knockout模型,我怀疑这会导致我的一些问题。我可以绑定/渲染记录的主要部分,我可以使用foreach模板绑定和呈现细节。但是,在我的场景中,我希望用户从子列表中选择要编辑的详细记录。问题是我无法让选择工作。我将点击事件触发,看来我的详细记录正在传递给我的事件 - 除了我无法读取属性的值。看着提琴手,看来正在通过的对象是事件的函数调用。在这一点上不太确定。所以,这是我的设置
我的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"
}]
}
Javascript来序列化JSON对象
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这样的数字,它是订单ID的值。不知道为什么会这样,但我做错了。
我已经将这些代码与一些与我正在做的类似的示例混合在一起。我可以完全以错误的方式解决这个问题,但我认为我只是错过了一些简单的事情。我确信那里的一些Javascrtipt神很容易看到我不知道的东西,所以我很感激你的帮助。
构建绑定的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>
答案 0 :(得分:0)
我建议您使用knockout映射为您可以从标记调用的数据项添加自定义功能。 (我为你创建了一个有效的JSBin)
您的初始数据保持不变,您的javascript变为:
var DataItem = function(data) {
var self = this;
ko.mapping.fromJS(data, {}, self);
// add custom functionality to each data item here
// here an alert is added that can be called via 'selectItem' in markup
self.selectItem = function(){
alert("item with id " + self.OrderId() + " clicked");
};
};
var viewModelMapping = {
'DataItems': {
create: function(options) {
return new DataItem(options.data);
}
}
};
var ViewModel = function(data) {
var self = this;
ko.mapping.fromJS(data, viewModelMapping, self);
};
var vm = new ViewModel(initialData);
$(document).ready(function () {
ko.applyBindings(vm);
});
并且您的HTML表格变为(为了清晰起见而删除了样式):
<table>
<tbody data-bind="foreach: DataItems">
<tr>
<td">
<input type="button" value="Select" data-bind="click: selectItem" />
<span data-bind="text: OrderId"></span>
</td>
<td data-bind="text: ItemHtml"></td>
</tr>
</tbody>
</table>
您可以在使用“创建”自定义对象构建和使用“更新”部分here自定义对象更新中阅读有关自定义映射对象的更多信息
答案 1 :(得分:0)
我认为问题是你应该删除#rotatorItems的jQuery绑定,并在.sel按钮上使用'click'绑定:
请看这个小提琴:
主要变化:
<tbody id="rotatorItems" data-bind="foreach: vmRotator.DataItems">
<tr>
<td style="width: 20px;">
<input type="button" class="sel" value="Select" data-bind="click: $root.selectRotatorItem" />
<span data-bind="text: OrderId"></span>
</td>
<td style="width: 90%;" data-bind="text: ItemHtml"></td>
</tr>
</tbody>