2013-08-22 92 views
3

我是相當新的淘汰賽,並試圖弄清楚如何把兩件我一起理解。敲除計算和輸入驗證

我需要:

  1. 項目依賴於對方。
  2. 對項目的輸入值驗證。

實施例:

  • 我在秒startTime,以秒爲duration,和stopTime是從startTime + duration計算
  • startTime不能改變
  • durationstopTime被綁定到輸入字段
  • stopTime顯示並輸入我ñHH: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添加到第一個塊中的計算結果中,它不起作用,因爲在HMSValidate的函數獲取值時它已被更改。

我已經通過添加另一個observable來跟蹤傳遞到計算中的「raw」值,然後添加另一個使用該值來判斷它是否爲錯誤狀態的計算,但它已在第一個塊中工作,但那並不覺得很優雅。

有沒有更好的方法?

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

回答

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,它充當原始可觀察對象的前端/過濾器。該可觀察者還有一些其他的子觀測值,即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()中),所以如果有人想出另一種方法來做到這一點,我都是耳朵。