繁体   English   中英

Knockout计算和输入验证

[英]Knockout computed and input validation

我是淘汰赛的新手,我想弄清楚如何将两件我理解的东西放在一起。

我需要:

  1. 相互依赖的项目。
  2. 对项目的输入值验证。

例:

  • 我有以秒为单位的startTime以秒为单位的duration以及从startTime + duration计算的stopTime
  • startTime无法更改
  • durationstopTime与输入字段相关联
  • 显示stopTime并以HH:MM:SS格式输入
  • 如果用户更改stopTime ,则应计算并自动更新duration
  • 如果用户更改duration ,则应计算并自动更新stopTime

我可以让它们互相更新(假设Sec2HMSHMS2Sec在别处定义,并在HH:MM:SS和秒之间转换):

this.startTime = 120; // Start at 120 seconds
this.duration = ko.observable(0);

// This dependency works by itself.
this.stopTimeFormatted = ko.computed({
    read: function () {
        return Sec2HMS(this.startTime + parseInt(this.duration()), true);
    },
    write: function (value) {
        var stopTimeSeconds = HMS2Sec(value);
        if (!isNaN(stopTimeSeconds)) {
            this.duration(stopTimeSeconds - this.startTime);
        } else {
            this.duration(0);
        }
    },
    owner: this
});

或者,我可以使用extendersfn验证输入,如敲除文档中所示:

ko.subscribable.fn.HMSValidate = function (errorMessage) {
    //add some sub-observables to our observable
    var observable = this;
    observable.hasError = ko.observable();
    observable.errorMessage = ko.observable();

    function validate(newValue) {
        var isInvalid = isNaN(HMS2Sec(newValue));
        observable.hasError(isInvalid ? true : false);
        observable.errorMessage(isInvalid ? errorMessage : null);
    }

    //initial validation
    validate(observable());

    //validate whenever the value changes
    observable.subscribe(validate);

    //return the original observable
    return observable;
};
this.startTime = 120; // Start at 120 seconds
this.duration = ko.observable(0);
this.stopTimeHMS = ko.observable("00:00:00").HMSValidate("HH:MM:SS please");

但是我如何让他们一起工作呢? 如果我将HMSValidate添加到第一个块中的计算中它不起作用,因为当HMSValidatevalidate函数获得它已经被更改的值时。

我通过添加另一个observable使其在第一个块中工作,该observable跟踪传递给计算器的“原始”值,然后添加另一个使用该值的计算器来判断它是否是错误状态,但是没有感觉非常优雅。

有没有更好的办法?

http://jsfiddle.net/cygnl7/njNaS/2/

经过一个星期的回收问题后,我回到了这个问题,我没有解决方法(代码清理时间!),这就是我所拥有的。

我最终提出了我在问题的最后提到的想法,但是将其封装在fn本身中。

ko.subscribable.fn.hmsValidate = function (errorMessage) {
    var origObservable = this;
    var rawValue = ko.observable(origObservable()); // Used for error checking without changing our main observable.
    if (!origObservable.hmsFormatValidator) {
        // Handy place to store the validator observable
        origObservable.hmsFormatValidator = ko.computed({
            read: function () {
                // Something else could have updated our observable, so keep our rawValue in sync.
                rawValue(origObservable());
                return origObservable();
            },
            write: function (newValue) {
                rawValue(newValue);
                if (newValue != origObservable() && !isNaN(HMS2Sec(newValue))) {
                    origObservable(newValue);
                }
            }
        });
        origObservable.hmsFormatValidator.hasError = ko.computed(function () {
            return isNaN(HMS2Sec(rawValue()));
        }, this);
        origObservable.hmsFormatValidator.errorMessage = ko.computed(function () {
            return errorMessage;
        }, this);
    }

    return origObservable.hmsFormatValidator;
};

这样做会创建另一个计算的observable,它作为原始observable的前置/过滤器。 该observable有一些其他的子可观察对象, hasErrorerrorMessage ,附加到它的错误状态。 rawValue会跟踪输入的值,以便我们可以检测它是否是一个好的值。 这可以处理我的一半要求。

至于使两个值相互依赖,我问题中的原始代码有效。 为了验证它,我添加了hmsValidate ,如下所示:

this.stopTimeFormatted = ko.computed({
    read: function () {
        return Sec2HMS(this.startTime + parseInt(this.duration()), true);
    },
    write: function (value) {
        this.duration(HMS2Sec(value) - this.startTime);
    },
    owner: this
}).hmsValidate("HH:MM:SS please");

在这里看到它: http//jsfiddle.net/cygnl7/tNV5S/1/

值得注意的是, write内部的验证不再是必要的,因为只有在正确验证的情况下,该值才会由hmsValidate写入。

这对我来说仍然感觉有点不雅,因为我正在检查isNaN几次并且必须跟踪原始值(特别是在read()中),所以如果有人想出另一种方法来做到这一点,我都是耳朵。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM