Wie beschränke ich eine Eingabe so, dass nur Zahlen akzeptiert werden?


92

Ich verwende ngChange in AngularJS, um eine benutzerdefinierte Funktion auszulösen, die alle Buchstaben entfernt, die der Benutzer der Eingabe hinzufügt.

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

Das Problem ist, dass ich auf die Eingabe abzielen muss, die ausgelöst wurde, numbersOnly()damit ich die eingegebenen Buchstaben entfernen kann. Ich habe lange und intensiv bei Google gesucht und konnte diesbezüglich nichts finden.

Was kann ich tun?


Dies ist auch eine gute Lösung, bei der keine Buchstaben eingegeben werden dürfen.
Himanshu Bhandari

Antworten:


104

Verwenden Sie auf einfache Weise type = "number", wenn dies für Ihren Anwendungsfall funktioniert:

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

Ein weiterer einfacher Weg: ng-pattern kann auch verwendet werden, um einen regulären Ausdruck zu definieren, der die zulässigen Felder einschränkt. Siehe auch die Seite "Kochbuch" über Formulare .

Hackisch? Art und Weise , beobachten $ ng-Modell in Ihrem Controller:

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

Regler:

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

Verwenden Sie am besten einen $ parser in einer Direktive. Ich werde die bereits gute Antwort von @ pkozlowski.opensource nicht wiederholen. Hier ist der Link: https://stackoverflow.com/a/14425022/215945

Bei allen oben genannten Lösungen wird das ng-Modell verwendet, wodurch das Auffinden thisunnötig wird.

Die Verwendung von ng-change führt zu Problemen. Siehe AngularJS - Zurücksetzen von $ scope.value ändert den Wert in der Vorlage nicht (zufälliges Verhalten)


Am Ende eine Richtlinie erstellt! Vielen Dank für den besten Weg. Ich habe ein bisschen recherchiert, aber ich habe viel gelernt!
Chris Bier

1
Kann jemand seine Nachteile auf die zuerst aufgeführte "einfache" Methode (Typ = "Nummer") erweitern, insbesondere im Vergleich zur empfohlenen "besten" Methode ($ parser in Direktive)?
Matt Welch

2
@ MattWelch, späte Antwort, aber der Nachteil ist die Browserunterstützung. Zumindest in Chrome type=numberwird automatisch der Spinner angezeigt, was möglicherweise unerwünscht ist. Sie können den Spinner über CSS ausblenden, aber auch das funktioniert möglicherweise nicht in allen Browsern.
Rosdi Kasim

3
Nur zwei Dinge, die beim Ansatz "easy" (type = "number") problematisch sein könnten, sind: 1. type = "number" erlaubt negatives Vorzeichen (-), Dezimaltrennzeichen (./,) und Exponentialschreibweise (e) und 2. Auf Samsung-Mobilgeräten können Sie keine negative Zahl in ein Feld vom Typ = "Zahl" eingeben (es gibt nur keine Minus-Taste auf der Tastatur)
Aides

Einfacher Weg ... Firefox ermöglicht die Eingabe von Zeichen in ein Feld nur für Zahlen. Es aktualisiert das Modell nicht, zeigt aber die Zeichen an
DRaehal

66

Verwenden ng-patterndes Textfelds:

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

Fügen Sie dies dann Ihrem Controller hinzu

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

Dies ist, was ich letztendlich basierend auf Marks Antwort getan habe, danke für die Beispiele! Ich bin sicher, es wird jemandem helfen!
Chris Bier

2
Dies funktioniert fast perfekt, ermöglicht aber dennoch die Eingabe von 'e'.
Kekse

Hilft wirklich, wenn Sie mit der Begrenzung von type = "number" und seiner Länge zu kämpfen haben. Die Lösung besteht darin, dieses ng-Muster zu verwenden und zu type = "text" zurückzukehren. Sehr ordentliche Lösung und entfernt eine Menge Code, der auf ng-change oder ng-keypress prüft. Bei dieser Lösung konnten keine E's eingegeben werden, daher gehe ich davon aus, dass dies ein weiteres Problem ist.
PeterS

1
Scheint mir browserspezifisch zu sein, ob keine numerische Eingabe zulässig ist oder nicht. In Chrome reicht es aus, nur <input type = 'number' /> zu verwenden, und es werden keine numerischen Eingaben zugelassen. Firefox hingegen mit demselben HTML-Code erlaubt Eingaben, löst jedoch das ungültige Eingabeflag aus, wenn der Wert nicht numerisch ist. Ich suche nach einer einfachen Möglichkeit, Chrome-Verhalten in allen Browsern zu erhalten
Steve

19

Keine der vorgeschlagenen Lösungen hat für mich gut funktioniert, und nach ein paar Stunden fand ich endlich den Weg.

Dies ist die Winkelrichtlinie:

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

Und die Eingabe würde so aussehen:

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

Der reguläre Ausdruck wertet die gedrückte Taste aus, nicht den Wert .

Es funktioniert auch perfekt mit Eingaben, type="number"da verhindert wird, dass sich sein Wert ändert, sodass der Schlüssel nie angezeigt wird und das Modell nicht beeinträchtigt wird.


Um Negative zuzulassen,restrict-to="[0-9\-]"
Noumenon

18

Hier ist meine Implementierung der $parserLösung, die @Mark Rajcok als beste Methode empfiehlt. Es ist im Wesentlichen @ pkozlowski.opensources ausgezeichneter $ Parser für Textantworten, der jedoch neu geschrieben wurde, um nur Zahlen zuzulassen. Alle Ehre gebührt ihm. Dies dient nur dazu, Ihnen die 5 Minuten des Lesens dieser Antwort und des anschließenden Umschreibens Ihrer eigenen zu ersparen:

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

Und du würdest es so benutzen:

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

Interessanterweise erreichen Leerzeichen den Parser nur, wenn sie von einer alphanumerischen Zahl umgeben sind .trim(). Sie müssen dies also nach Bedarf tun . Auch dieser Parser ist nicht arbeiten <input type="number">. Aus irgendeinem Grunde, nicht-numerische Werte machen es nie an den Parser , wo sie entfernt werden würde, aber sie tun es in die Eingangskontrolle selbst.


Als ich dies implementierte, bekam ich JS-Fehler, wenn das Modell der Eingabe ohne Wert initialisiert wurde. Durch diese Änderung wurde var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
Folgendes

Danke @Alkie. Ich habe diese Änderung in die Richtlinie aufgenommen.
Mordred

1
Sie müssen festlegen , ng-trimum falseum sicherzustellen , dass Räume erreichen Ihre Parser zu machen.
Ilya

Um es perfekt zu machen, müssen Sie modelCtrl.$commitViewValue();zwischen $ setViewValue (clean) hinzufügen ; und $ render ();
Ingaham

1
Danke dir! Das ist einfach großartig! Es hat sehr geholfen
iulial

4

Es gibt einige Möglichkeiten, dies zu tun.

Sie könnten verwenden type="number":

<input type="number" />

Alternativ - Ich habe dafür eine wiederverwendbare Direktive erstellt , die einen regulären Ausdruck verwendet.

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 () {// deine Logik}); Dies verhindert, dass auch nur der unerwünschte Wert
eingegeben

4

Hier ist eine ziemlich gute Lösung, um nur die Eingabe der Nummer zuzulassen input:

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

Dies erlaubt mir nicht, Löschen oder
Rücktaste

Löschen und Rücktaste funktioniert jedoch. Getestet auf Firefox 76.0.1
iamjoshua

3

Alle oben genannten Lösungen sind ziemlich groß, ich wollte meine 2 Cent dafür geben.

Ich überprüfe nur, ob der eingegebene Wert eine Zahl ist oder nicht, und ob er nicht leer ist, das ist alles.

Hier ist das HTML:

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

Hier ist der JS:

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

Es ist ganz einfach.

Ich glaube, das wird bei Paste tho nicht funktionieren, nur damit es bekannt ist.

Ich denke, für Paste müssten Sie das onChange-Ereignis verwenden und den gesamten String analysieren, ein ganz anderes Biest, das Tamme. Dies ist spezifisch für die Eingabe.

UPDATE zum Einfügen : Fügen Sie einfach diese JS-Funktion hinzu:

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

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

Und die HTML-Eingabe fügt den Auslöser hinzu:

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

Ich hoffe das hilft o /


2

Hier ist ein Plunker , der jede Situation behandelt, die über dem Vorschlag nicht behandelt wird.
Durch Verwendung der Pipeline $ formatters und $ parsers und Vermeidung von type = "number"

Und hier ist die Erklärung der Probleme / Lösungen (auch im Plunker verfügbar):

/*
 *
 * 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)
 *
 */

1
   <input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />

Sie können nur numerische Attribute verwenden.


1

DEZIMAL

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

Ziffern

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

Winkelanweisungen zum Validieren von Zahlen


0

Ich weiß, dass dies alt ist, aber ich habe eine Richtlinie für diesen Zweck erstellt, falls jemand nach einer einfachen Lösung sucht. Sehr einfach zu bedienen.

Sie können es hier überprüfen .


0

Vielleicht möchten Sie auch die 0 am Anfang der Eingabe entfernen ... Ich füge einfach einen if-Block zur obigen Mordred-Antwort hinzu, da ich noch keinen Kommentar abgeben kann ...

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

0

Versuche dies,

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

}

0

LÖSUNG: Ich mache eine Anweisung für alle Eingaben, Zahlen, Texte oder andere in der App, damit Sie einen Wert eingeben und das Ereignis ändern können. Machen Sie für Winkel 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">

-1

Am Ende habe ich eine modifizierte Direktive des obigen Codes erstellt, um Eingaben zu akzeptieren und das Format im laufenden Betrieb zu ändern ...

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

})


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

1
Code-Dumping wird normalerweise verpönt. Bitte fügen Sie eine Erklärung hinzu.
Rayryeng

1
Versuchen Sie zum Einschränken des Tastendrucks diese - - - Funktion Nummer (evt) {var charCode = (evt.which)? evt.which: event.keyCode if (charCode> 31 && (charCode <48 || charCode> 57)) return false; return true; <input type = "number" min = "0" onkeypress = "return Number (event)">
Rahul Sharma

-1

Grundlegendes HTML

<input type="number" />

Grundlegender Bootstrap

<input class="form-control" type="number" value="42" id="my-id">

@Praveen Ich stimme dir nicht zu, die Frage erwähnt keinen Bootstrap. warum sollten wir erwähnen, dass etwas in der Frage nicht existiert?
Amr Ibrahim

wenn wir Bootstrap verwenden wollen <input class="form-control" type="number" >
Amr Ibrahim
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.