How do I restrict an input to only accept numbers?

210,215

Solution 1

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

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

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

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

<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

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

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

Solution 2

Using ng-pattern on the text field:

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

Then include this on your controller

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

Solution 3

Here's my implementation of the $parser solution that @Mark Rajcok recommends as the best method. It's essentially @pkozlowski.opensource's excellent $parser for text answer but 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:

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 NOT work on <input type="number">. For some reason, non-numerics never make it to the parser where they'd be removed, but they do make it into the input control itself.

Solution 4

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.

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.

Solution 5

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

<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
Share:
210,215
Chris Bier
Author by

Chris Bier

Jesus is my life! Please read John chapter 3 in the Bible :) Web Developer &amp; Graphic Designer HTML, CSS, Javascript, PHP

Updated on February 18, 2020

Comments

  • Chris Bier
    Chris Bier over 4 years

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

    <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.

    What can I do?