Knockout Custom Binding foreach

Я пытаюсь создать сводку проверки со списком ссылок на ошибки для Библиотека проверки 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>

person williamparry    schedule 24.03.2013    source источник


Ответы (1)


В этом мне помог пользователь Stackoverflow @antishok на IRC-канале #knockoutjs:

Коду требуется 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>
person williamparry    schedule 25.03.2013