链接Knockout自定义绑定

时间:2013-09-13 22:37:04

标签: javascript jquery knockout.js custom-binding

我有一个Knockout自定义绑定处理程序,我想在其中调用foreach绑定功能,然后调用回调函数。我一直得到一个“未捕获的错误:你不能多次将绑定应用于同一个元素。”现在我尝试这样做了。

我的自定义绑定非常简单(打字稿):

/// <reference path="knockout.d.ts" />
ko.bindingHandlers["postForeach"] = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        if (!allBindingsAccessor().postForeachCallback)
            throw "Callback not defined for postForeach binding!";

        //call foreach init functionality
        ko.bindingHandlers['foreach'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            //call foreach update functionality
            ko.bindingHandlers['foreach'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
            //call callback
            allBindingsAccessor().postForeachCallback();
    }
};

我在构建它时是否缺少某些内容?

谢谢!

编辑:

回调功能

self.populateMainContentWindow = function () {
                    var dataTable = $(this.tableId).dataTable();
        dataTable.fnDestroy();

                // create the datatable
                        var actualTable = this.jQuery(this.tableId);
        if (actualTable.length == 0) {
            return false;
        }

        // create the data table with options
        var newDataTable = actualTable.dataTable(this.options);

        // always set the width afterwards
        actualTable.css("width", "100%");
            };

数据绑定签名(在'with'绑定中):

postForeach: array, postForeachCallback: $parent.viewModel().populateMainContentWindow

3 个答案:

答案 0 :(得分:6)

Knockout使用init的返回值来确定它是否应该处理元素的后代。您可以只返回foreach.init函数的值,也可以从{ controlsDescendantBindings: true }函数返回init

init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    if (!allBindingsAccessor().postForeachCallback)
        throw "Callback not defined for postForeach binding!";

    //call foreach init functionality
    return ko.bindingHandlers['foreach'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
},

参考:http://knockoutjs.com/documentation/custom-bindings-controlling-descendant-bindings.html

答案 1 :(得分:2)

变体1
我认为你当前的绑定看起来像

data-bind="foreach: someArray, postForeach: ..."  

您可以在value绑定中为foreach绑定设置postForeach。例如:

data-bind="postForeach : 
           {postForeachCallback : function()
                                  {
                                    alert('After')
                                  },
           foreach: someArray}" // this is your old foreach  

绑定:

ko.bindingHandlers["postForeach"] = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        if (!valueAccessor().postForeachCallback)
            throw "Callback not defined for postForeach binding!";

        //call foreach init functionality
        return ko.bindingHandlers['foreach'].init(element, valueAccessor().foreach, allBindingsAccessor, viewModel, bindingContext);
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            //call foreach update functionality
            ko.bindingHandlers['foreach'].update(element, valueAccessor().foreach, allBindingsAccessor, viewModel, bindingContext);
            //call callback
            valueAccessor().postForeachCallback();
    }
};  

JSFiddle DEMO

变体2
视图模型中的此varian视图模型(innerViewModel)。此视图模型与with绑定绑定 现在data-bind看起来像

data-bind="postForeach : true, postForeachCallback : $parent.postCallback, foreachEx: values"  

视图看起来像

<div data-bind="with: innerViewModel">
   <ul data-bind="postForeach : true, postForeachCallback : $parent.postCallback, foreachEx: values">
       <li data-bind="text: val"></li>
   </ul>
</div>

JSFiddle DEMO

答案 2 :(得分:1)

它看起来与您发布的代码无关。相反,看起来有多次调用applyBindings,其中两个调用同一个元素。

示例:http://jsfiddle.net/tlarson/bFKuL/ (在控制台中查看错误)

var vm = {
    Name: "George"
}
ko.applyBindings(vm);
ko.applyBindings(vm);

标记:

<div data-bind="text:Name"></div>

要解决此问题,请不要在同一元素上调用applyBindings两次。为了帮助您确切了解如何使用代码执行此操作,我们需要查看更多代码,例如演示此问题的小提琴。