如何限制input只接受数字?
我在AngularJS中使用ngChange来触发一个自定义函数,它将删除用户添加到input的任何字母。
<input type="text" name="inputName" data-ng-change="numbersOnly()"/>
问题是我需要针对触发numbersOnly()
的input,以便我可以删除input的字母。 我在Google上看了很久,很难find任何关于这方面的信息。
我能做什么?
简单的方法 ,如果它适用于您的用例,请使用type =“number” :
<input type="number" ng-model="myText" name="inputName">
另一个简单的方法: ng-pattern也可以用来定义一个正则expression式,这个正则expression式会限制这个字段中允许的内容。 另见关于表格的“食谱”页面 。
hackish的? 方法 $在你的控制器中观察ng模型:
<input type="text" ng-model="myText" name="inputName">
控制器:
$scope.$watch('myText', function() { // put numbersOnly() logic here, eg: if ($scope.myText ... regex to look for ... ) { // strip out the non-numbers } })
最好的方法是在指令中使用$ parser。 我不打算重复@ pkozlowski.opensource提供的已经很好的答案,所以这里的链接: https ://stackoverflow.com/a/14425022/215945
所有上述解决scheme都涉及使用ng-model,这使得findthis
不必要的。
使用ng-change会导致问题。 请参阅AngularJS – 重置$ scope.value不会更改模板中的值(随机行为)
在文本字段中使用ng-pattern
:
<input type="text" ng-model="myText" name="inputName" ng-pattern="onlyNumbers">
然后将其包含在您的控制器中
$scope.onlyNumbers = /^\d+$/;
所提出的解决scheme都没有为我工作得很好,几个小时后,我终于find了方法。
这是angular度指令:
angular.module('app').directive('restrictTo', function() { return { restrict: 'A', link: function (scope, element, attrs) { var re = RegExp(attrs.restrictTo); var exclude = /Backspace|Enter|Tab|Delete|Del|ArrowUp|Up|ArrowDown|Down|ArrowLeft|Left|ArrowRight|Right/; element[0].addEventListener('keydown', function(event) { if (!exclude.test(event.key) && !re.test(event.key)) { event.preventDefault(); } }); } } });
input将如下所示:
<input type="number" min="0" name="inputName" ng-model="myModel" restrict-to="[0-9]">
正则expression式评估按下的键,而不是值 。
它也可以很好地处理inputtype="number"
因为防止改变它的值,所以密钥从不显示,也不会混淆模型。
这里是我的$parser
解决scheme的实现@Mark Rajcokbuild议作为最好的方法。 它本质上是@ pkozlowski.opensource 优秀的$parsing器文本答案,但重写只允许数字。 所有的荣誉都归功于他,这只是为了节省你阅读答案的5分钟,然后重写你自己的:
app.directive('numericOnly', function(){ return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function (inputValue) { var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null; if (transformedInput!=inputValue) { modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); } return transformedInput; }); } }; });
你会这样使用它:
<input type="text" name="number" ng-model="num_things" numeric-only>
有趣的是,除非字母数字包围,否则空格不会到达parsing器,所以您必须根据需要使用.trim()
。 此外,这个parsing器不能在<input type="number">
。 出于某种原因,非数字从来不会将它们传递给parsing器,在那里它们将被移除,但是它们确实将其input到input控件本身中。
有几种方法可以做到这一点。
你可以使用type="number"
:
<input type="number" />
另外 – 我为此创build了一个可重用的指令 ,使用正则expression式。
HTML
<div ng-app="myawesomeapp"> test: <input restrict-input="^[0-9-]*$" maxlength="20" type="text" class="test" /> </div>
使用Javascript
;(function(){ var app = angular.module('myawesomeapp',[]) .directive('restrictInput', [function(){ return { restrict: 'A', link: function (scope, element, attrs) { var ele = element[0]; var regex = RegExp(attrs.restrictInput); var value = ele.value; ele.addEventListener('keyup',function(e){ if (regex.test(ele.value)){ value = ele.value; }else{ ele.value = value; } }); } }; }]); }());
这里是一个处理任何以上命题不处理的情况。
通过使用$格式化程序和$parsing器pipe道,避免type =“number”
这里是问题/解决scheme的解释(也可在Plunker中获得):
/* * * Limit input text for floating numbers. * It does not display characters and can limit the Float value to X numbers of integers and X numbers of decimals. * min and max attributes can be added. They can be Integers as well as Floating values. * * value needed | directive * ------------------------------------ * 55 | max-integer="2" * 55.55 | max-integer="4" decimal="2" (decimals are substracted from total length. Same logic as database NUMBER type) * * * Input type="number" (HTML5) * * Browser compatibility for input type="number" : * Chrome : - if first letter is a String : allows everything * - if first letter is a Integer : allows [0-9] and "." and "e" (exponential) * Firefox : allows everything * Internet Explorer : allows everything * * Why you should not use input type="number" : * When using input type="number" the $parser pipeline of ngModel controller won't be able to access NaN values. * For example : viewValue = '1e' -> $parsers parameter value = "". * This is because undefined values are not allowes by default (which can be changed, but better not do it) * This makes it impossible to modify the view and model value; to get the view value, pop last character, apply to the view and return to the model. * * About the ngModel controller pipelines : * view value -> $parsers -> model value * model value -> $formatters -> view value * * About the $parsers pipeline : * It is an array of functions executed in ascending order. * When used with input type="number" : * This array has 2 default functions, one of them transforms the datatype of the value from String to Number. * To be able to change the value easier (substring), it is better to have access to a String rather than a Number. * To access a String, the custom function added to the $parsers pipeline should be unshifted rather than pushed. * Unshift gives the closest access to the view. * * About the $formatters pipeline : * It is executed in descending order * When used with input type="number" * Default function transforms the value datatype from Number to String. * To access a String, push to this pipeline. (push brings the function closest to the view value) * * The flow : * When changing ngModel where the directive stands : (In this case only the view has to be changed. $parsers returns the changed model) * -When the value do not has to be modified : * $parsers -> $render(); * -When the value has to be modified : * $parsers(view value) --(does view needs to be changed?) -> $render(); * | | * | $setViewValue(changedViewValue) * | | * --<-------<---------<--------<------ * * When changing ngModel where the directive does not stand : * - When the value does not has to be modified : * -$formatters(model value)-->-- view value * -When the value has to be changed * -$formatters(model vale)-->--(does the value has to be modified) -- (when loop $parsers loop is finished, return modified value)-->view value * | * $setViewValue(notChangedValue) giving back the non changed value allows the $parsers handle the 'bad' value * | and avoids it to think the value did not changed * Changed the model <----(the above $parsers loop occurs) * */
DECIMAL
directive('decimal', function() { return { require: 'ngModel', restrict: 'A', link: function(scope, element, attr, ctrl) { function inputValue(val) { if (val) { var digits = val.replace(/[^0-9.]/g, ''); if (digits.split('.').length > 2) { digits = digits.substring(0, digits.length - 1); } if (digits !== val) { ctrl.$setViewValue(digits); ctrl.$render(); } return parseFloat(digits); } return ""; } ctrl.$parsers.push(inputValue); } }; });
DIGITS
directive('entero', function() { return { require: 'ngModel', restrict: 'A', link: function(scope, element, attr, ctrl) { function inputValue(val) { if (val) { var value = val + ''; //convert to string var digits = value.replace(/[^0-9]/g, ''); if (digits !== value) { ctrl.$setViewValue(digits); ctrl.$render(); } return parseInt(digits); } return ""; } ctrl.$parsers.push(inputValue); } }; });
validation号码的angular度指令
我知道这是旧的,但我已经为此目的创build了一个指令,以防有人在寻找一个简单的解决scheme。 使用非常简单。
你可以在这里查看
你可能还想删除在input的开始0 …我只是添加一个if块以上Mordred的答案,因为我还不能发表评论…
app.directive('numericOnly', function() { return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function (inputValue) { var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null; if (transformedInput!=inputValue) { modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); } //clear beginning 0 if(transformedInput == 0){ modelCtrl.$setViewValue(null); modelCtrl.$render(); } return transformedInput; }); } }; })
基本和干净的HTML方式
<input type="number" />
<input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />
您可以使用数字属性。
这是一个很好的解决scheme,只允许input号码input
:
<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
我最终创build了上面的代码的修改指令,以接受input和dynamic更改格式…
.directive('numericOnly', function($filter) { return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { element.bind('keyup', function (inputValue, e) { var strinput = modelCtrl.$$rawModelValue; //filter user input var transformedInput = strinput ? strinput.replace(/[^,\d.-]/g,'') : null; //remove trailing 0 if(transformedInput.charAt(0) <= '0'){ transformedInput = null; modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); }else{ var decimalSplit = transformedInput.split(".") var intPart = decimalSplit[0]; var decPart = decimalSplit[1]; //remove previously formated number intPart = intPart.replace(/,/g, ""); //split whole number into array of 3 digits if(intPart.length > 3){ var intDiv = Math.floor(intPart.length / 3); var strfraction = []; var i = intDiv, j = 3; while(intDiv > 0){ strfraction[intDiv] = intPart.slice(intPart.length-j,intPart.length - (j - 3)); j=j+3; intDiv--; } var k = j-3; if((intPart.length-k) > 0){ strfraction[0] = intPart.slice(0,intPart.length-k); } } //join arrays if(strfraction == undefined){ return;} var currencyformat = strfraction.join(','); //check for leading comma if(currencyformat.charAt(0)==','){ currencyformat = currencyformat.slice(1); } if(decPart == undefined){ modelCtrl.$setViewValue(currencyformat); modelCtrl.$render(); return; }else{ currencyformat = currencyformat + "." + decPart.slice(0,2); modelCtrl.$setViewValue(currencyformat); modelCtrl.$render(); } } }); } };
})
<input type="text" ng-model="employee.age" valid-input input-pattern="[^0-9]+" placeholder="Enter an age" /> <script> var app = angular.module('app', []); app.controller('dataCtrl', function($scope) { }); app.directive('validInput', function() { return { require: '?ngModel', scope: { "inputPattern": '@' }, link: function(scope, element, attrs, ngModelCtrl) { var regexp = null; if (scope.inputPattern !== undefined) { regexp = new RegExp(scope.inputPattern, "g"); } if(!ngModelCtrl) { return; } ngModelCtrl.$parsers.push(function(val) { if (regexp) { var clean = val.replace(regexp, ''); if (val !== clean) { ngModelCtrl.$setViewValue(clean); ngModelCtrl.$render(); } return clean; } else { return val; } }); element.bind('keypress', function(event) { if(event.keyCode === 32) { event.preventDefault(); } }); } }}); </script>