Validation 导致触发计算值的自定义验证

Validation 导致触发计算值的自定义验证,validation,knockout.js,Validation,Knockout.js,为了快速了解我的问题,我制作了一个工作JSFIDLE: 在KnockoutJS中,我制作了一个定制的扩展验证程序来测试输入格式是否为HHMM格式。如果是,则返回新值,如果不是,则将其设置回当前工作的旧值 ko.extenders.acValidTimeHHMM = function (target, options) { var result = ko.computed({ read: target, write: function (newValue) { v

为了快速了解我的问题,我制作了一个工作JSFIDLE:

在KnockoutJS中,我制作了一个定制的扩展验证程序来测试输入格式是否为HHMM格式。如果是,则返回新值,如果不是,则将其设置回当前工作的旧值

ko.extenders.acValidTimeHHMM = function (target, options) {
var result = ko.computed({
    read: target, 
    write: function (newValue) {
        var re = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[0-5][0-9]$/;
        if (!re.test(newValue)) {
            target.notifySubscribers(target());
            //Time not in correct format return old time
            return;
        }
        target(newValue);
    }
}).extend({ notify: 'always' });

result(target());
return result;
};
我遇到的问题是,当值更改时,我使用计算出的值更新数据库。但是,当我使用验证器将值重置回其原始值时,也会触发此操作。(基于Ryan Rahlf脏旗技术的方法)

问题显然是行target.notifySubscribers(target());在我的验证器中。但是,如果没有这一行,我无法将该值重置为其旧值,也无法找到其他方法来执行此操作

因此,这仅在值实际更改时触发,而不是验证程序重置它。JSFIDLE准确地演示了我的问题,可以用来制作一个工作版本(希望如此),我知道它当前也会在页面加载时启动

我遇到的问题是,当值更改时,我使用计算出的值更新数据库

我不知道您的所有逻辑,但我认为每次更新淘汰视图模型时更新db不是一个好主意。也许你应该看看。使用此插件,您可以构建相同的自定义验证规则,并仅在表单提交事件中更新db

关于你的问题。。。 我发现的最简单的解决方案是向验证扩展发送一个成功回调函数,就像一个选项一样。 差不多

JS:

HTML:

第一次

第二次


谢谢Max-您的解决方案为我提供了一个很好的解决方案。通过更新数据库,我实际上只是根据输入时间获取信息(这必须是实时的),因此需要在成功更新时调用它。
self.update = ko.computed(function () {
    self.timeOne();
    self.timeTwo();
    alert("Fired");
});
var ViewModel = function() {  
    var update = function () {
        alert("value was successfully changed");
    };

    var cancel = function () {
        alert("validation failed. previous value was returned");
    };

    var timeOne = ko.observable("1100").
        extend({ 
                    acValidTimeHHMM: { 
                        success: update,
                        fail: cancel
                    }
               });

    var timeTwo = ko.observable("1248").
        extend({ acValidTimeHHMM: { success: update } });

    return {
        timeOne: timeOne,
        timeTwo: timeTwo
    };
};

ko.extenders.acValidTimeHHMM = function(target, option) {    
    var baseOptions = {
        success: null,
        fail: null
    };
    $.extend(baseOptions, option);

    var result = ko.computed({
        read: target, 
        write: function (newValue) {
            var oldValue = target();
            if(newValue == oldValue) return;

            var re = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[0-5][0-9]$/;
            if (!re.test(newValue)) {
                target.notifySubscribers(oldValue);
                if(typeof(baseOptions.fail) == "function")
                    baseOptions.fail();
                return;
            }
            target(newValue);

            if(typeof(baseOptions.success) == "function")
                baseOptions.success()
        }
    }).extend({ notify: 'always' });

    result(target());
    return result;
};

ko.applyBindings(new ViewModel());
<p>Time One<input data-bind='value: timeOne' /></p> 
<p>Time Two<input data-bind='value: timeTwo' /></p>