【问题标题】:Knockout custom binding does not show initial viewModel data properly淘汰赛自定义绑定未正确显示初始 viewModel 数据
【发布时间】:2012-01-24 18:48:35
【问题描述】:

我使用第三方插件使表格可编辑。所以我需要为

创建一个自定义绑定,以便插件引起的对文本的任何更改都会触发视图模型更新。但是自定义绑定不显示正确的数据,而不是内置的“文本”绑定。我做错什么了吗?

请看: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();
});

【问题讨论】:

    标签: jquery knockout.js jquery-plugins custom-binding


    【解决方案1】:

    在您的update 函数中,您需要解开可观察对象。 valueAccessor() 会给你 observable 本身,然后你会想要解开它(调用它作为一个函数)来获取值。

    一个安全的方法是使用ko.utils.unwrapObservable,因为它可以容忍可观察的和不可观察的。

    因此,您的更新将如下所示:

        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            $(element).text(value);
        }
    

    此外,在您的小提琴中,您在 Knockout 之后列出了 jQuery.tmpl,因此 KO 没有注册 jQuery 模板引擎。

    这是一个更新的小提琴:http://jsfiddle.net/rniemeyer/VbeBA/8/

    更新: 最终解决方案在http://jsfiddle.net/rniemeyer/qQaUa/

    【讨论】:

    • 其实我以前也试过这个。但对我来说问题是它会使 jQuery Editable 插件不起作用。小提琴jsfiddle.net/justinc/VbeBA/9 显示可编辑可在 Firefox 上正常工作,但不能在初始绑定上工作,而 jsfiddle.net/justinc/VbeBA/10 显示可编辑不能与未包装的可观察对象一起使用。也许 Knockout 和 Editable 之间存在事件时间冲突?
    • 问题实际上是您的模板正在根据${variable} jQuery 模板调用(创建依赖项)重新呈现。这些是不必要的,因为您已经在使用绑定。这是一个示例:jsfiddle.net/rniemeyer/VbeBA/11
    • 又添加了一项更新:jsfiddle.net/rniemeyer/qQaUa。当您访问更新函数中的基础值时,它会创建对可观察对象的依赖,这很好。但是,当在 change handler 中更新 observable 时,会触发 update 函数,最终导致内容为空。更改处理程序只需要在当前执行上下文完成后运行它的更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    相关资源
    最近更新 更多