[英]Knockout computed and input validation
我是淘汰賽的新手,我想弄清楚如何將兩件我理解的東西放在一起。
我需要:
例:
startTime
以秒為單位的duration
以及從startTime + duration
計算的stopTime
startTime
無法更改 duration
和stopTime
與輸入字段相關聯 stopTime
並以HH:MM:SS
格式輸入 stopTime
,則應計算並自動更新duration
duration
,則應計算並自動更新stopTime
我可以讓它們互相更新(假設Sec2HMS
和HMS2Sec
在別處定義,並在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
});
或者,我可以使用extenders
或fn
驗證輸入,如敲除文檔中所示:
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
添加到第一個塊中的計算中它不起作用,因為當HMSValidate
的validate
函數獲得它已經被更改的值時。
我通過添加另一個observable使其在第一個塊中工作,該observable跟蹤傳遞給計算器的“原始”值,然后添加另一個使用該值的計算器來判斷它是否是錯誤狀態,但是沒有感覺非常優雅。
有沒有更好的辦法?
經過一個星期的回收問題后,我回到了這個問題,我沒有解決方法(代碼清理時間!),這就是我所擁有的。
我最終提出了我在問題的最后提到的想法,但是將其封裝在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有一些其他的子可觀察對象, hasError
和errorMessage
,附加到它的錯誤狀態。 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.