Javascript 如何将输入限制为仅接受数字?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14615236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:24:14  来源:igfitidea点击:

How do I restrict an input to only accept numbers?

javascriptangularjsangularjs-directive

提问by Chris Bier

I am using ngChange in AngularJS to trigger a custom function that will remove any letters the user adds to the input.

我在 AngularJS 中使用 ngChange 来触发一个自定义函数,该函数将删除用户添加到输入中的任何字母。

<input type="text" name="inputName" data-ng-change="numbersOnly()"/>

The problem is that I need to target the input that triggered numbersOnly()so that I can remove the letters entered. I have looked long and hard on Google and was unable to find anything regarding this.

问题是我需要定位触发的输入,numbersOnly()以便我可以删除输入的字母。我在谷歌上搜索了很长时间,但找不到任何关于此的信息。

What can I do?

我能做什么?

回答by Mark Rajcok

Easy way, use type="number"if it works for your use case:

简单的方法,如果它适用于您的用例,请使用type="number"

<input type="number" ng-model="myText" name="inputName">

Another easy way:ng-patterncan also be used to define a regex that will limit what is allowed in the field. See also the "cookbook" page about forms.

另一种简单的方法:ng-pattern也可用于定义一个正则表达式,该表达式将限制该字段中允许的内容。另请参阅有关表单“食谱”页面

Hackish? way, $watch the ng-model in your controller:

黑客?way, $watch 控制器中的 ng-model:

<input type="text"  ng-model="myText" name="inputName">

Controller:

控制器:

$scope.$watch('myText', function() {
   // put numbersOnly() logic here, e.g.:
   if ($scope.myText  ... regex to look for ... ) {
      // strip out the non-numbers
   }
})

Best way, use a $parser in a directive. I'm not going to repeat the already good answer provided by @pkozlowski.opensource, so here's the link: https://stackoverflow.com/a/14425022/215945

最好的方法是在指令中使用 $parser。我不会重复@pkozlowski.opensource 提供的已经很好的答案,所以这里是链接:https://stackoverflow.com/a/14425022/215945

All of the above solutions involve using ng-model, which make finding thisunnecessary.

以上所有解决方案都涉及使用 ng-model,这使得查找变得this不必要。

Using ng-change will cause problems. See AngularJS - reset of $scope.value doesn't change value in template (random behavior)

使用 ng-change 会导致问题。请参阅AngularJS - $scope.value 的重置不会改变模板中的值(随机行为)

回答by MarkJ

Using ng-patternon the text field:

使用ng-pattern该文本字段:

<input type="text"  ng-model="myText" name="inputName" ng-pattern="onlyNumbers">

Then include this on your controller

然后将其包含在您的控制器上

$scope.onlyNumbers = /^\d+$/;

回答by Mordred

Here's my implementation of the $parsersolution that @Mark Rajcok recommends as the best method. It's essentially @pkozlowski.opensource's excellent $parser for text answerbut rewritten to only allow numerics. All credit goes to him, this is just to save you the 5 minutes of reading that answer and then rewriting your own:

这是我对$parser@Mark Rajcok 推荐为最佳方法的解决方案的实现。它本质上是@pkozlowski.opensource出色的 $parser 文本答案,但重写为仅允许数字。所有功劳都归功于他,这只是为了节省您阅读该答案的 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;
            });
        }
    };
});

And you'd use it like this:

你会像这样使用它:

<input type="text" name="number" ng-model="num_things" numeric-only>

Interestingly, spaces never reach the parser unless surrounded by an alphanumeric, so you'd have to .trim()as needed. Also, this parser does NOTwork on <input type="number">. For some reason, non-numerics never make it to the parser where they'd be removed, but they domake it into the input control itself.

有趣的是,除非被字母数字包围,否则空格永远不会到达解析器,因此您必须.trim()根据需要。此外,该解析器不会工作的<input type="number">。出于某种原因,非数字永远不会进入解析器将它们删除的地方,但它们确实进入了输入控件本身。

回答by ragnar

None of the solutions proposed worked fine for me, and after a couple of hours I finally found the way.

提出的解决方案都没有对我有用,几个小时后我终于找到了方法。

This is the angular directive:

这是角度指令:

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();
                }
            });
        }
    }
});

And the input would look like:

输入看起来像:

<input type="number" min="0" name="inputName" ng-model="myModel" restrict-to="[0-9]">

The regular expression evaluates the pressed key, not the value.

正则表达式计算按下的键,而不是 value

It also works perfectly with inputs type="number"because prevents from changing its value, so the key is never displayed and it does not mess with the model.

它还可以完美地与输入一起使用,type="number"因为它可以防止更改其值,因此密钥永远不会显示并且不会与模型混淆。

回答by Peter Rasmussen

There are a few ways to do this.

有几种方法可以做到这一点。

You could use type="number":

你可以使用type="number"

<input type="number" />

Alternatively - I created a reuseable directivefor this that uses a regular expression.

或者 - 我为此创建了一个使用正则表达式的可重用指令

Html

html

<div ng-app="myawesomeapp">
    test: <input restrict-input="^[0-9-]*$" maxlength="20" type="text" class="test" />
</div>

Javascript

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;
                    }
                });
            }
        };
    }]);    
}());

回答by Zorkind

All the above solutions are quite large, i wanted to give my 2 cents on this.

以上所有解决方案都很大,我想为此付出 2 美分。

I am only checking if the value inputed is a number or not, and checking if it's not blank, that's all.

我只是检查输入的值是否是数字,并检查它是否不是空白,仅此而已。

Here is the html:

这是html:

<input type="text" ng-keypress="CheckNumber()"/>

Here is the JS:

这是JS:

$scope.CheckKey = function () {
    if (isNaN(event.key) || event.key === ' ' || event.key === '') {
        event.returnValue = '';
    }
};

It's quite simple.

这很简单。

I belive this wont work on Paste tho, just so it's known.

我相信这不会在 Paste 上工作,只是众所周知。

For Paste, i think you would need to use the onChange event and parse the whole string, quite another beast the tamme. This is specific for typing.

对于粘贴,我认为您需要使用 onChange 事件并解析整个字符串,这是另一种野兽。这是特定于打字的。

UPDATE for Paste: just add this JS function:

Paste 更新:只需添加此 JS 函数:

$scope.CheckPaste = function () {
    var paste = event.clipboardData.getData('text');

    if (isNaN(paste)) {
        event.preventDefault();
        return false;
    }
};

And the html input add the trigger:

并且 html 输入添加触发器:

<input type="text" ng-paste="CheckPaste()"/>

I hope this helps o/

我希望这有助于o/

回答by Raniys

Here is a pretty good solution to makes only allow enter number to the input:

这是一个非常好的解决方案,只允许输入数字input

<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>

回答by gr3g

Here is a Plunkerhandling any situation above proposition do not handle.
By using $formatters and $parsers pipeline and avoiding type="number"

这是一个处理上述命题不处理的任何情况的Plunker
通过使用 $formatters 和 $parsers 管道并避免 type="number"

And here is the explanation of problems/solutions (also available in the Plunker) :

这是问题/解决方案的解释(也可在 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)
 *
 */

回答by Angeldev

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);
                }
            };
        });

angular directives for validate numbers

用于验证数字的角度指令

回答by Joee

Try this,

尝试这个,

<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();
    }

}