2013-06-11 195 views
17

我看了很多教程,但我不知道如何做到這一點只能輸入數字型,這是輸入作出淘汰賽

input(type="text",name="price",id="price"data-bind="text: price,valueUpdate:['afterkeydown','propertychange','input']") 

,這是我的ViewModel

price: ko.computed(function() 
{ 
    return parseFloat(this.replace(' ','').replace(/[^0-9\.]+/g,"")) || ''; 
},this) 

但這導致錯誤:這沒有方法替換?我如何將價格值傳遞給計算函數?

+1

而不是'input type =「text」',如果將其更改爲'input type =「number」',該怎麼辦?我認爲這些限制你將它們放入數值中。 – jonhopkins

+3

type =「number」與某些瀏覽器的兼容性較差 – andrescabana86

+1

Jon是正確的,因爲您可以將類型更改爲數字,但如果我沒有記錯,並非所有瀏覽器都支持該類型。例如,我相信任何事情之前,IE10讓你把課文中有沒有問題 –

回答

37

最好創建自定義綁定http://knockoutjs.com/documentation/custom-bindings.html,它只接受允許的字符[0-9 ,.]作爲數字表示。

,就把這行到你的觀點

<input id="text" type="text" data-bind="numeric, value: number"> 

,就把這行到你的模型(記得要結合作爲觀察的特性數)

ko.bindingHandlers.numeric = { 
    init: function (element, valueAccessor) { 
     $(element).on("keydown", function (event) { 
      // Allow: backspace, delete, tab, escape, and enter 
      if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 || 
       // Allow: Ctrl+A 
       (event.keyCode == 65 && event.ctrlKey === true) || 
       // Allow: . , 
       (event.keyCode == 188 || event.keyCode == 190 || event.keyCode == 110) || 
       // Allow: home, end, left, right 
       (event.keyCode >= 35 && event.keyCode <= 39)) { 
       // let it happen, don't do anything 
       return; 
      } 
      else { 
       // Ensure that it is a number and stop the keypress 
       if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105)) { 
        event.preventDefault(); 
       } 
      } 
     }); 
    } 
}; 
+2

這真的有用嗎?對我來說,它不會更新Observable,如果它在用戶界面的某個地方?例如,您有如上所述的以及一些。在這種情況下,如果用戶在輸入內編輯編號,編輯完成後UI不會更新。 – renathy

+0

從輸入字段更改焦點後將應用更改。下面是實時編輯的簡單示例(無焦點更改)。 http://jsfiddle.net/jakethashi/L7UEm/ –

+0

@renathy我離開了textInput綁定,並添加了數字作爲第二個綁定,效果很好 – LobsterMan

1

的另一種方法:我發現,剔除效果很好結合jQuery-validate。您只需確保在嘗試使用數字值之前驗證表單。

假設你有一個表單DOM元素,你可以設置通過

$(".yourform").validate({ 
    rules: { 
     year: { 
      digits: true, 
      minlength: 4, 
      maxlength: 4 
     } 
    }, 
    messages: { 
     year: "Please enter four digits (e.g. 2009).", 
    } 
}); 

在您的視圖模型設置了雙向綁定像往常一樣,例如驗證規則通過self.year = ko.observable("")。現在請確保您在進一步處理self.year()之前致電$(".yourform").valid()。在我的情況下,我在做var year = parseInt(self.year(), 10)。在表單驗證之後,預計這將始終產生有意義的結果。

7

淘汰賽有這個擴展。來自knockoutjs.com的Check This解釋瞭如何使用可觀察的擴展器來強制輸入爲數字。我粘貼代碼從這裏的文檔:

源代碼:查看

<p><input data-bind="value: myNumberOne" /> (round to whole number)</p> 
<p><input data-bind="value: myNumberTwo" /> (round to two decimals)</p> 

源代碼:查看模式

ko.extenders.numeric = function(target, precision) { 
    //create a writable computed observable to intercept writes to our observable 
    var result = ko.pureComputed({ 
     read: target, //always return the original observables value 
     write: function(newValue) { 
      var current = target(), 
       roundingMultiplier = Math.pow(10, precision), 
       newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue), 
       valueToWrite = Math.round(newValueAsNum * roundingMultiplier)/roundingMultiplier; 

      //only write if it changed 
      if (valueToWrite !== current) { 
       target(valueToWrite); 
      } else { 
       //if the rounded value is the same, but a different value was written, force a notification for the current field 
       if (newValue !== current) { 
        target.notifySubscribers(valueToWrite); 
       } 
      } 
     } 
    }).extend({ notify: 'always' }); 

    //initialize with current value to make sure it is rounded appropriately 
    result(target()); 

    //return the new computed observable 
    return result; 
}; 

function AppViewModel(one, two) { 
    this.myNumberOne = ko.observable(one).extend({ numeric: 0 }); 
    this.myNumberTwo = ko.observable(two).extend({ numeric: 2 }); 
} 

ko.applyBindings(new AppViewModel(221.2234, 123.4525)); 
1
<input type="text" id="alpha-validation" data-bind="value: YourDataName, valueUpdate: 'afterkeydown' , event: { 'input': AlphaCheck}" style="text-transform:uppercase"> 

創建AlphaCheck功能,並添加。

$('#alpha-validation').keyup(function() { 
     if (this.value.match(/[^0-9 ]/g)) { 
      this.value = this.value.replace(/[^0-9 ]/g, ''); 
     } 
    }); 

這將起作用!

-1

我知道這個問題是一歲,但讓我發佈此爲頁面的功能遊客着想。

檢查了這一點:

ko.bindingHandlers.numericnumbers = { 
init: function (element) { 
    $(element).on('keypress', function (number) { 
     number = (number) ? number : window.event; 
     var charcode = (number.which) ? number.which : number.keyCode; 
     if (charcode > 31 && (charcode < 48 || charcode > 75)) 
      number.preventDefault(); 
    }); 
}}; 
0

創建您的數據綁定在你的閃閃發光的新代碼指向:

<input id="price" name="price" type="text" data-bind="numeric"> 

嶄新的淘汰賽代碼:

price = ko.observable(); 
price.subscribe(function(newValue) { 
    price = newValue.replace(/[\D\.]/g, ''); 
}); 

這意味着每當你更新價格時,它會應用函數中的邏輯(在這種情況下剝離出任何東西不是數字或期限),並將其直接應用於價格。您還可以在這裏添加其他驗證或很酷的功能,比如在開始添加貨幣sybmol,維持到小數點後2位,等等...

0

用「的keydown」事件的幫助下,我們可以限制在文字等關鍵的應該包含數字值的框。

$(document).ready(function(){     
     $("selector").on("keydown", function (e) { 
      //numbers, delete, backspace, arrows 
      var validKeyCodes = [8, 9, 37, 38, 39, 40, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]; 
      if (!($.inArray(e.keyCode, validKeyCodes) >= 0)) 
        e.preventDefault();     
     });   
    }); 
0

我們可以限制用戶輸入用戶超過兩位十進制數字。 23.81,3452.83修改後的代碼如下。參考代碼來自@Martin Surynek答案。

HTML -

<p> 
    <input data-bind="value: myNumberOne" /> (round to whole number)</p> 
    <p> 
    <input data-bind="num, value: myNumberTwo" /> (round to two decimals)</p> 

腳本 -

<script> 
    ko.bindingHandlers.num = { 
     init: function (element, valueAccessor) { 
     $(element).on("keypress", function (event) { 
      //debugger 
      console.log(event.keyCode); 
      var $this = $(this); 
      var text = $this.val(); 

      // Stop insert two dots 
      if ($this.val().indexOf('.') != -1 && (event.which == 190 || event.which == 110)) { 
      event.preventDefault(); 
      } 

      // Allow: backspace, delete, tab, escape, and enter 
      if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 
      13 || 
      // Allow: Ctrl+A 
      (event.keyCode == 65 && event.ctrlKey === true) || 
      // Allow: . ,event.keyCode == 188 || 
      (event.keyCode == 190 || event.keyCode == 110) || 
      // Allow: home, end, left, right 
      (event.keyCode >= 35 && event.keyCode <= 39)) { 
      // let it happen, don't do anything 
      return; 
      } 

      // Ensure that it is a number and stop the keypress 
      if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 
       105)) { 
      event.preventDefault(); 
      } 

      if ((event.which == 46) && (text.indexOf('.') == -1)) { 
      setTimeout(function() { 
       if ($this.val().substring($this.val().indexOf('.')).length > 3) { 
       $this.val($this.val().substring(0, $this.val().indexOf('.') + 3)); 
       } 
      }, 1); 
      } 

      if ((text.indexOf('.') != -1) && 
      (text.substring(text.indexOf('.')).length > 2) && 
      (event.which != 0 && event.which != 8) && 
      ($(this)[0].selectionStart >= text.length - 2)) { 
      event.preventDefault(); 
      }   
      //console.log($(this)[0].selectionStart >= text.length - 2); 
     }); 
     } 
    }; 


    ko.extenders.numeric = function (target, precision) { 
     //create a writable computed observable to intercept writes to our observable 

     var result = ko.pureComputed({ 
     read: target, //always return the original observables value 
     write: function (newValue) { 

      var current = target(), 
      roundingMultiplier = Math.pow(10, precision), 
      newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue), 
      valueToWrite = Math.round(newValueAsNum * roundingMultiplier)/roundingMultiplier; 

      //only write if it changed 
      if (valueToWrite !== current) { 
      target(valueToWrite); 
      } else { 
      //if the rounded value is the same, but a different value was written, force a notification for the current field 
      if (newValue !== current) { 
       target.notifySubscribers(valueToWrite); 
      } 
      } 
     } 
     }).extend({ 
     notify: 'always' 
     }); 

     //initialize with current value to make sure it is rounded appropriately 
     result(target()); 

     //return the new computed observable 
     return result; 
    }; 

    function AppViewModel(one, two) { 
     this.myNumberOne = ko.observable(one).extend({ 
     numeric: 0 
     }); 
     this.myNumberTwo = ko.observable(two).extend({ 
     numeric: 2 
     }); 
    } 

    ko.applyBindings(new AppViewModel(221.2234, 123.4525)); 
    </script> 
0

我也有類似的問題。

我還需要確保只有內部值,對於IE9和以上(因此type = numberical是不夠的),並且由於我們有很多國際客戶,所以我不能依賴鍵碼,因此以下是我結束了:

//In my js class method (self is this as usual) 
self.ensureNumberical = function (data, e) { 
    var keyValue = e.key; 
    if (keyValue.match(/[0-9]/g)) { 
     return true; 
    } 
    return false; 
} 

//In my MVC View 
data-bind="event: { keypress: ensureNumberical }"