2013-06-11 148 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 }"