如何将输入限制为仅接受数字?
Posted
技术标签:
【中文标题】如何将输入限制为仅接受数字?【英文标题】:How do I restrict an input to only accept numbers? 【发布时间】:2013-01-14 22:21:51 【问题描述】:我在 AngularJS 中使用 ngChange 来触发一个自定义函数,该函数将删除用户添加到输入中的任何字母。
<input type="text" name="inputName" data-ng-change="numbersOnly()"/>
问题是我需要定位触发numbersOnly()
的输入,以便删除输入的字母。我在 Google 上搜索了很久,但找不到任何相关信息。
我能做什么?
【问题讨论】:
This 也是一个很好的解决方案,不允许输入字母。 html Text Input allow only Numeric input的可能重复 【参考方案1】:基本 HTML
<input type="number" />
基本引导
<input class="form-control" type="number" value="42" id="my-id">
【讨论】:
@Praveen 我不同意你的观点,这个问题没有提到任何引导程序。为什么我们应该提到问题中不存在的东西? 如果我们想使用引导程序<input class="form-control" type="number" >
【参考方案2】:
简单的方法,如果它适用于您的用例,请使用 type="number":
<input type="number" ng-model="myText" name="inputName">
另一种简单的方法: ng-pattern 也可以用来定义一个正则表达式来限制字段中允许的内容。另请参阅"cookbook" page about forms。
骇客?方式,$watch 控制器中的 ng-model:
<input type="text" ng-model="myText" name="inputName">
控制器:
$scope.$watch('myText', function()
// put numbersOnly() logic here, e.g.:
if ($scope.myText ... regex to look for ... )
// strip out the non-numbers
)
最佳方式,在指令中使用 $parser。 我不会重复@pkozlowski.opensource 提供的已经很好的答案,所以这里是链接:https://***.com/a/14425022/215945
上述所有解决方案都涉及使用 ng-model,这使得查找 this
变得不必要。
使用 ng-change 会导致问题。见AngularJS - reset of $scope.value doesn't change value in template (random behavior)
【讨论】:
最终创建了一个指令!感谢您提供最好的方法。进行了一些研究,但我学到了很多东西! 任何人都能够将缺点扩展到首先列出的“简单”方式(type="number"),特别是与推荐的“最佳”方式($parser in directive)相比? @MattWelch,迟到的答案,但缺点是浏览器支持。至少在 Chrome 中,type=number
会自动显示微调器,这可能是不受欢迎的。您可以通过 css 隐藏微调器,但即便如此,这也可能不适用于所有浏览器。
只有两件事可能与“简单”(type="number")方法存在问题,即 1. type="number" 允许负号 (-)、小数分隔符 (./, ) 和指数符号 (e) 和 2. 在三星移动设备上,您不能在 type="number" 字段中输入负数(键盘上没有减号键)
简单方法... firefox 允许将字符输入到仅数字字段中。它不会更新模型,但会显示字符【参考方案3】:
解决方案: 我为应用程序中的所有输入、数字、文本或任何内容创建了一个指令,因此您可以输入一个值并更改事件。 制作角度 6
import Directive, ElementRef, HostListener, Input from '@angular/core';
@Directive(
// tslint:disable-next-line:directive-selector
selector: 'input[inputType]'
)
export class InputTypeDirective
constructor(private _el: ElementRef)
@Input() inputType: string;
// tipos: number, letter, cuit, tel
@HostListener('input', ['$event']) onInputChange(event)
if (!event.data)
return;
switch (this.inputType)
case 'number':
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
if (initalValue !== this._el.nativeElement.value)
event.stopPropagation();
break;
case 'text':
const result = event.data.match(/[^a-zA-Z Ññ]*/g);
if (result[0] !== '')
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(
/[^a-zA-Z Ññ]*/g,
''
);
event.stopPropagation();
break;
case 'tel':
case 'cuit':
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(/[^0-9-]*/g, '');
if (initalValue !== this._el.nativeElement.value)
event.stopPropagation();
HTML
<input matInput inputType="number" [formControlName]="field.name" [maxlength]="field.length" [placeholder]="field.label | translate" type="text" class="filter-input">
【讨论】:
【参考方案4】:以上所有解决方案都很大,我想为此付出我的 2 美分。
我只是检查输入的值是否为数字,检查是否为空,仅此而已。
这里是html:
<input type="text" ng-keypress="CheckNumber()"/>
这里是 JS:
$scope.CheckKey = function ()
if (isNaN(event.key) || event.key === ' ' || event.key === '')
event.returnValue = '';
;
这很简单。
我相信这在 Paste tho 上不起作用,只是众所周知。
对于粘贴,我认为您需要使用 onChange 事件并解析整个字符串,这完全是另一种野兽。这是专门用于打字的。
粘贴更新:只需添加这个 JS 函数:
$scope.CheckPaste = function ()
var paste = event.clipboardData.getData('text');
if (isNaN(paste))
event.preventDefault();
return false;
;
并且html输入添加触发器:
<input type="text" ng-paste="CheckPaste()"/>
我希望这有助于o/
【讨论】:
【参考方案5】:试试这个,
<input ng-keypress="validation($event)">
function validation(event)
var theEvent = event || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
var regex = /[0-9]|\./;
if (!regex.test(key))
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault();
【讨论】:
【参考方案6】:十进制
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);
;
);
数字
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);
;
);
angular directives for validate numbers
【讨论】:
【参考方案7】:这是一个很好的解决方案,只允许在input
中输入数字:
<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
【讨论】:
这不允许我按删除或退格键 删除和退格虽然有效。在 Firefox 76.0.1 上测试【参考方案8】:在文本字段上使用ng-pattern
:
<input type="text" ng-model="myText" name="inputName" ng-pattern="onlyNumbers">
然后将其包含在您的控制器上
$scope.onlyNumbers = /^\d+$/;
【讨论】:
这是我根据 Marks 的回答最终做的事情,不过感谢您提供的示例!我相信它会帮助别人! 这几乎可以完美运行,但仍然允许输入“e”。 如果您正在努力限制 type="number" 和它的长度,这真的很有帮助。解决方案是使用此 ng 模式并恢复为 type="text"。非常整洁的解决方案,消除了对 ng-change 或 ng-keypress 的大量代码检查。此解决方案不允许输入“e”,因此我假设这是另一个问题。 在我看来是特定于浏览器的,它是否允许无数字输入。在 Chrome 上,简单地使用 就足够了,它不允许任何非数字输入,另一方面,具有相同 Html 的 Firefox 将允许任何输入,但如果值不是数字,则会触发无效输入标志。我正在寻找一种在所有浏览器上获取 Chrome 行为的简单方法【参考方案9】:所提出的解决方案都不适合我,几个小时后我终于找到了方法。
这是角度指令:
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 type="number" min="0" name="inputName" ng-model="myModel" restrict-to="[0-9]">
正则表达式计算按下的键,而不是值。
它还可以完美地与输入 type="number"
配合使用,因为它可以防止更改其值,因此密钥永远不会显示并且不会与模型混淆。
【讨论】:
允许否定,restrict-to="[0-9\-]"
【参考方案10】:
<input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />
您可以使用纯数字属性。
【讨论】:
【参考方案11】:<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>
【讨论】:
代码转储通常不受欢迎。请添加一些解释。 对于限制按键试试这个 - - - function Number(evt) var charCode = (evt.which) ? evt.which : event.keyCode if (charCode > 31 && (charCode 57)) 返回 false;返回真; 【参考方案12】:我最终创建了上述代码的修改指令来接受输入并即时更改格式...
.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();
);
;
)
【讨论】:
【参考方案13】:您可能还想删除输入开头的 0...我只是在上面的 Mordred 答案中添加了一个 if 块,因为我还不能发表评论...
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;
);
;
)
【讨论】:
【参考方案14】:这是一个Plunker处理上述任何情况的建议不要处理。 通过使用 $formatters 和 $parsers 管道并避免 type="number"
这里是问题/解决方案的解释(也可以在 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)
*
*/
【讨论】:
【参考方案15】:有几种方法可以做到这一点。
你可以使用type="number"
:
<input type="number" />
或者 - 我为此创建了一个可重用的directive,它使用正则表达式。
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;
);
;
]);
());
【讨论】:
use, $(element).on('input', function() // 你的逻辑 );这甚至可以防止输入不需要的值【参考方案16】:我知道这是旧的,但我为此创建了一个指令,以防有人正在寻找一个简单的解决方案。使用非常简单。
您可以查看here。
【讨论】:
【参考方案17】:这是我对@Mark Rajcok 推荐为最佳方法的$parser
解决方案的实现。它本质上是@pkozlowski.opensource 的excellent $parser for text answer,但被重写为只允许使用数字。所有功劳归他所有,这只是为了节省您阅读该答案然后重写您自己的 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>
有趣的是,除非被字母数字包围,否则空格永远不会到达解析器,因此您必须根据需要.trim()
。此外,此解析器不在<input type="number">
上工作。出于某种原因,非数字永远不会进入解析器,在那里它们将被删除,但它们确实进入输入控件本身。
【讨论】:
当我实现这个时,如果输入的模型在没有值的情况下被初始化,我会得到 JS 错误。进行此更改解决了:var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
谢谢@Alkie。我将该更改添加到指令中。
您必须将 ng-trim
设置为 false
以确保空格到达您的解析器。
为了使其完美,您需要在 $setViewValue(clean); 之间添加 modelCtrl.$commitViewValue();
和 $render();
谢谢!这太棒了!帮助很大以上是关于如何将输入限制为仅接受数字?的主要内容,如果未能解决你的问题,请参考以下文章