如何将Knockout验证附加到自定义绑定

时间:2015-04-17 23:21:58

标签: javascript knockout.js knockout-validation

我创建了一个Knockout自定义绑定,使用moment.js格式化日期。

ko.bindingHandlers.dateStringValue = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = valueAccessor(),
        allBindings = allBindingsAccessor();
        var valueUnwrapped = ko.utils.unwrapObservable(value);

        if (valueUnwrapped === null) {
            ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
            $(element).val("");
        } else {
            ko.bindingHandlers.value.update(element, valueAccessor, allBindingsAccessor, viewModel);
            var pattern = allBindings.datePattern || "MM/DD/YYYY";
            $(element).val(moment(valueUnwrapped).format(pattern));
        }
    }
};

这适用于我的绑定:

<input type="text" data-bind="dateStringValue: entryDate, datePattern: 'M/D/YYYY'" />

我使用网络上的代码创建了自定义验证规则。

// http://stackoverflow.com/a/23086828/139917
// Use: var someDate= ko.observable().extend({ simpleDate: true });
// Dependencies: date.js
ko.validation.rules['simpleDate'] = {
    validator: function (val, validate) {
        var d = Date.parse(val);
        return (d != null);
        //return ko.validation.utils.isEmptyVal(val) || moment(val, 'MM/DD/YYYY').isValid();
    },
    message: 'Invalid date entry date'
};

ko.validation.registerExtenders();

我尝试了moment.js和date.js日期库。

我将自定义验证规则附加到我的viewmodel observable。

self.entryDate = ko.observable(je.entryDate || new Date()).extend({ simpleDate: true });

现在我想使用Knockout Validation验证输入,但不知道如何让验证框架了解我的新绑定。似乎Knockout Validation只知道一些或所有内置的Knockout绑定。

调用ko.validation.makeBindingHandlerValidatable("dateStringValue");会在Knockout v3.2.0中引发0x800a138f - JavaScript runtime error: Object expected错误。有人建议从我的自定义绑定调用Knockout值绑定会起作用,但像ko.bindingHandlers.value.update(element, valueAccessor);这样的代码对我来说没有用。

如何让Knockout Validation了解我的自定义绑定?

3 个答案:

答案 0 :(得分:0)

通过将新参数传递给绑定,在自定义绑定中创建验证,即:

<input type="text" data-bind="customDate: { value: entryDate, pattern: 'M/D/YYYY'", validatable: true } />

在你的装订中做一些魔法。

答案 1 :(得分:0)

这是我如何解决我的问题。我在我的实体上创建了一个读/写计算属性,并使用了moment.js来验证输入:

var dateFormatString = "M/D/YYYY"

self.entryDate = ko.observable(je.entryDate || new Date());
self.formattedEntryDate = ko.computed({
    read: function () {
        return moment(self.entryDate()).format(dateFormatString);
    },
    write: function (value) {
        var momentDate = moment(value, dateFormatString);
        if (momentDate.isValid()) {
            self.entryDate(momentDate.format(dateFormatString));
            self.isValidEntryDate(true);
            return;
        }
        self.isValidEntryDate(false);
    },
    owner: self
});
self.isValidEntryDate = ko.observable(true);

如果输入字符串不是预期的格式,我会将isValidEntryDate observable设置为false,这会向用户显示一条消息,提示他们重新输入日期。

<input type="text" data-bind="value: formattedEntryDate" />
<div class="validationMessage" data-bind="hidden: isValidEntryDate">Invalid entry date. Use M/D/YYYY format.</div>

此绑定使用hidden的自定义绑定处理程序。

我意识到这并没有解决问题,但以生产力的名义,这实现了目标。

随意直接回答这个问题。

答案 2 :(得分:0)

我的工作方式如下 -

<input type="text" data-bind="dateStringValue: entryDate.extend({ simpleDate: entryDate()}), datePattern: 'M/D/YYYY'" />