【问题标题】:Knockout computed and input validation淘汰赛计算和输入验证
【发布时间】:2013-09-04 23:09:18
【问题描述】:

我对淘汰赛还很陌生,正在尝试弄清楚如何将我理解的两个部分组合在一起。

我需要:

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

例子:

  • 我有startTime 以秒为单位,duration 以秒为单位,stopTimestartTime + duration 计算得出
  • startTime 无法更改
  • durationstopTime 绑定到输入字段
  • stopTimeHH:MM:SS 格式显示和输入
  • 如果用户更改stopTimeduration应该被计算并自动更新
  • 如果用户改变durationstopTime应该被计算并自动更新

我可以让它们相互更新(假设 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 来跟踪传递给计算的“原始”值,然后添加另一个使用该值来确定它是否是错误状态的计算,但是感觉不是很优雅。

有没有更好的办法?

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

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

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

    我最终得到了我在问题末尾提到的想法,但将其封装在 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 有一些其他子 observables,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() 中),所以如果有人想出另一种方法来做到这一点,我都在听。

    【讨论】:

      猜你喜欢
      • 2012-02-18
      • 1970-01-01
      • 2012-03-08
      • 2012-06-12
      • 2014-02-01
      • 2015-02-03
      • 2011-08-09
      • 2014-12-13
      • 2014-10-13
      相关资源
      最近更新 更多