2

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

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

从我所看到的(有点相关)我的范围错误 - 因为在“ko.applyBindingsToDescendants”中需要子元素的 ViewModel,但我不确定如何实现这一点。

这是我当前的绑定代码:

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>
4

1 回答 1

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>
于 2013-03-25T01:13:01.803 回答