簡體   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