使用AJAX调用问题解锁自定义验证

时间:2017-02-14 18:53:43

标签: javascript ajax validation knockout.js

我的自定义验证将验证输入到表单字段中的邮政编码是否对从前一字段中的下拉列表中选择的状态有效。当我第一次选择状态然后输入有效/无效的zip时,它工作正常。但是,如果它验证然后我去选择不同的状态,则不会触发验证错误消息。谁能告诉我我缺少什么,为什么不重新验证?

自定义验证:

ko.validation.rules["isValidZipCode"] =
    {
        async: true,
        getValue: function (o) {
            return (typeof o === 'function' ? o() : o);
        },
        validator: function (val, fields, callBack) {
            var self = this;
            var anyOne = ko.utils.arrayFirst(fields, function (field) {
                var val = self.getValue(field);

                if (val === undefined || val === null) 
                    return "";                
                return true;
            });

            var ajaxData = { state: anyOne, zipCode: val }
            $.ajax({
                url: $("a#ValidateZipByState").attr("href"),
                type: "POST",
                data: ajaxData,
                success: function (isValid) {
                    if (isValid) {
                        callBack(true);
                    } else {
                        callBack(false);
                    }
                },
                error: handleSubmitError
            });

            return;
        },
        message: "Invalid zip code for this state"
    };

视图模型:

self.State = ko.observable(model.State).extend({ required: true });
self.ZipCode = ko.observable(model.ZipCode).extend({ required: true, pattern: /^[0-9]{5}(?:-[0-9]{4})?$/g, isValidZipCode: [self.State, self.ZipCode] });

2 个答案:

答案 0 :(得分:1)

您可以添加订阅状态并使用 ko.validation.validateObservable 方法触发ZipCode上的验证 - 此外,由于此验证规则特定于ZipCode,您可以使用匿名自定义规则。

self.State = ko.observable("StateB").extend({ 
    required: true
});

self.State.subscribe(function(){
    ko.validation.validateObservable(self.ZipCode);
})

self.ZipCode = ko.observable(789).extend({
    validation: {
        async: true,
        validator: function (val, params, callback) {
            setTimeout(function() {
                var zips = stateZips.get(self.State());
                var exists = zips.some(function(zip) {
                    return zip == new Number(val);
                });
                return callback(exists);
            });
        },
        message: "Invalid zip code for this state"
    }
});

此处完成示例:JSFiddle

编辑:为了让状态触发验证(不首先更改ZipCode),您必须使用:

ko.validation.init({ messagesOnModified: false });

答案 1 :(得分:0)

看起来验证规则仅附加到ZipCode observable,因此更新State值本身不会触发新的验证。如果我正确理解问题,您必须更新状态,然后在更新发生之前对邮政编码进行另一次更改。

如果是这样,你可能想尝试这个快速的黑客攻击,以便在状态发生变化时更新验证:

self.State.subscribe(function(newValue){
    self.ZipCode.valueHasMutated();
});