Knockout Custom Binding foreach

时间:2013-03-24 22:38:13

标签: jquery knockout.js knockout-validation

我正在尝试创建一个验证摘要,其中包含指向KnockoutJS Validation Library错误的链接列表,我需要创建一个自定义foreach处理程序来呈现它。

使用下面的代码我想要实现的是能够监听errors()列表中的更改并构建验证摘要。我实际上并没有使用“错误”列表(因为它只是一个字符串列表),而是用它来听取变化。

从我看过的内容(somewhat related)我认为范围错误 - 就像“ko.applyBindingsToDescendants”期望子元素的ViewModel一样,但我不确定如何实现它。 / p>

这是我目前的绑定代码:

ko.bindingHandlers.validationSummary = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        function ValidationErrorModel(fieldRef, errorMessage) {
            this.fieldRef = ko.observable(fieldRef),
            this.errorMessage = ko.observable(errorMessage)
        }

        var currentValidationModel = ko.observableArray(),
            $validationElements = $(".validationElement");

        $validationElements.each(function (i, elem) {

            var $elem = $(elem),
                validationErrorModel = new ValidationErrorModel("#" + $elem.attr("name"), $elem.attr("title"));

            currentValidationModel.push(validationErrorModel);

        });

        console.log(currentValidationModel());
        ko.applyBindingsToDescendants({ foreach: currentValidationModel }, element);


        return { controlsDescendantBindings: true };
    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

    }
};

我的模板:

<ul data-bind="validationSummary: errors">
    <li>
        <a data-bind="attr: { href: fieldRef }, text: errorMessage"></a>
    </li>
</ul>

1 个答案:

答案 0 :(得分:2)

Stackoverflow用户@antishok在#knockoutjs IRC频道帮我解决了这个问题:

  

代码需要一个setTimeout,因为只有在触发错误后才会使用类和属性更新元素

自定义绑定:

ko.bindingHandlers.validationSummary = {

    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        var value = valueAccessor();
        value(); // register dependency

        function ValidationErrorModel(fieldRef, errorMessage) {
            this.fieldRef = ko.observable(fieldRef),
            this.errorMessage = ko.observable(errorMessage)
        }

        setTimeout(function() {
            var currentValidationModel = 
                $(".validationElement").map(function(i, elem) {
                    var $elem = $(elem);
                    return new ValidationErrorModel("#" + $elem.attr("name"), $elem.attr("title"));
                }).get();

            ko.bindingHandlers.foreach.update(element, function() { return currentValidationModel }, allBindingsAccessor, viewModel, bindingContext);
        }, 0);
    }
};

HTML:

<ul data-bind="validationSummary: errors">
    <li>
        <a data-bind="attr: { href: fieldRef }, text: errorMessage"></a>
    </li>
</ul>