淘汰赛自定义绑定无法正确显示初始 viewModel 数据
我使用第三方插件来使表格可编辑。所以我需要为 创建自定义绑定这样插件引起的任何文本更改都会触发视图模型更新。但与内置“文本”绑定相反,自定义绑定不会显示正确的数据。我做错了什么吗?
请参阅: http://jsfiddle.net/VbeBA/5
HTML:
<table id="table1" cellspacing="0" cellpadding="0" border="0">
<tr>
<th style="width:150px">Product</th>
<th>Price ($)</th>
<th>Quantity</th>
<th>Amount ($)</th>
</tr>
<tbody data-bind='template: {name: "orderTemplate", foreach: orders}'></tbody>
</table>
<script type="text/html" id="orderTemplate">
<tr>
<td data-bind="text: product">${product}</td>
<td class="editable number" data-bind="dataCell: price"></td>
<td class="editable number"data-bind="dataCell: quantity">${quantity}</td>
<td class="number" data-bind="text: amount">${amount}</td>
</tr>
</script>
CSS:
table
{
border: solid 1px #e8eef4;
border-collapse: collapse;
}
table th
{
padding: 6px 5px;
background-color: #e8eef4;
border: solid 1px #e8eef4;
}
table td
{
padding:0 3px 0 3px;
margin: 0px;
height: 20px;
border: solid 1px #e8eef4;
}
td.number
{
width: 100px;
text-align:right;
}
td.editable
{
background-color:#fff;
}
td.editable input
{
font-family: Verdana, Helvetica, Sans-Serif;
text-align: right;
width: 100%;
height: 100%;
border: 0;
}
td.editing
{
border: 2px solid Blue;
}
脚本:
$(function () {
ko.bindingHandlers.dataCell = {
init: function (element, valueAccessor) {
ko.utils.registerEventHandler(element, "change", function () {
var value = valueAccessor();
value($(element).text());
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
$(element).text(value);
}
};
var order = function (product, price, quantity) {
this.product = product;
this.price = ko.observable(price);
this.quantity = ko.observable(quantity);
this.amount = ko.dependentObservable(function () {
return this.price() * this.quantity();
}, this);
}
var ordersModel = function () {
this.orders = ko.observableArray([]);
}
var viewModel = new ordersModel();
viewModel.orders = ko.observableArray([
new order("Gala Apple", 0.79, 150),
new order("Naval Orange", 0.29, 500)
]);
ko.applyBindings(viewModel);
$(".editable").change();
});
I use a third-party plugin to make a table editable. So I need to create a custom binding for <td> so that any changes to the text caused by the plugin would trigger a view model update. But the custom binding does not show correct data, as opposed to the built-in 'text' binding. Did I do anything wrong?
Please see: http://jsfiddle.net/VbeBA/5
HTML:
<table id="table1" cellspacing="0" cellpadding="0" border="0">
<tr>
<th style="width:150px">Product</th>
<th>Price ($)</th>
<th>Quantity</th>
<th>Amount ($)</th>
</tr>
<tbody data-bind='template: {name: "orderTemplate", foreach: orders}'></tbody>
</table>
<script type="text/html" id="orderTemplate">
<tr>
<td data-bind="text: product">${product}</td>
<td class="editable number" data-bind="dataCell: price"></td>
<td class="editable number"data-bind="dataCell: quantity">${quantity}</td>
<td class="number" data-bind="text: amount">${amount}</td>
</tr>
</script>
CSS:
table
{
border: solid 1px #e8eef4;
border-collapse: collapse;
}
table th
{
padding: 6px 5px;
background-color: #e8eef4;
border: solid 1px #e8eef4;
}
table td
{
padding:0 3px 0 3px;
margin: 0px;
height: 20px;
border: solid 1px #e8eef4;
}
td.number
{
width: 100px;
text-align:right;
}
td.editable
{
background-color:#fff;
}
td.editable input
{
font-family: Verdana, Helvetica, Sans-Serif;
text-align: right;
width: 100%;
height: 100%;
border: 0;
}
td.editing
{
border: 2px solid Blue;
}
Script:
$(function () {
ko.bindingHandlers.dataCell = {
init: function (element, valueAccessor) {
ko.utils.registerEventHandler(element, "change", function () {
var value = valueAccessor();
value($(element).text());
});
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor();
$(element).text(value);
}
};
var order = function (product, price, quantity) {
this.product = product;
this.price = ko.observable(price);
this.quantity = ko.observable(quantity);
this.amount = ko.dependentObservable(function () {
return this.price() * this.quantity();
}, this);
}
var ordersModel = function () {
this.orders = ko.observableArray([]);
}
var viewModel = new ordersModel();
viewModel.orders = ko.observableArray([
new order("Gala Apple", 0.79, 150),
new order("Naval Orange", 0.29, 500)
]);
ko.applyBindings(viewModel);
$(".editable").change();
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的
update
函数中,您需要解开可观察对象。valueAccessor()
将为您提供可观察对象本身,然后您需要解开它(将其作为函数调用)以获取值。一种安全的方法是使用 ko.utils.unwrapObservable,因为它可以容忍可观察值和不可观察值。
因此,您的更新将如下所示:
此外,在您的小提琴中,您在 Knockout 之后列出了 jQuery.tmpl,因此 KO 没有注册 jQuery 模板引擎。
这是更新的小提琴: http://jsfiddle.net/rniemeyer/VbeBA/8/
更新:
最终解决方案位于 http://jsfiddle.net/rniemeyer/qQaUa/
In your
update
function you will want to unwrap the observable.valueAccessor()
is going to give you the observable itself and then you would want to unwrap it (call it as a function) to get the value.A safe way to do that is to use
ko.utils.unwrapObservable
as it will tolerate both observables and non-observables.So, your update would look like:
Additionally, in your fiddle you had jQuery.tmpl listed after Knockout, so KO did not register the jQuery template engine.
Here is an updated fiddle: http://jsfiddle.net/rniemeyer/VbeBA/8/
Updated:
The final solution is at http://jsfiddle.net/rniemeyer/qQaUa/