Bagaimana cara membatasi input hanya untuk menerima nomor?

92

Saya menggunakan ngChange di AngularJS untuk memicu fungsi kustom yang akan menghapus semua huruf yang ditambahkan pengguna ke input.

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

Masalahnya adalah saya harus menargetkan masukan yang dipicu numbersOnly()sehingga saya dapat menghapus huruf yang dimasukkan. Saya telah mencari lama dan keras di Google dan tidak dapat menemukan apa pun tentang ini.

Apa yang dapat saya?

Chris Bier
sumber
Ini juga merupakan solusi yang baik, yang tidak memungkinkan untuk memasukkan huruf.
Himanshu Bhandari
Kemungkinan duplikat dari Input Teks HTML hanya mengizinkan input Numerik
Shobhit Srivastava

Jawaban:

104

Cara mudah , gunakan type = "number" jika berfungsi untuk kasus penggunaan Anda:

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

Cara mudah lainnya: ng-pattern juga dapat digunakan untuk mendefinisikan regex yang akan membatasi apa yang diperbolehkan di lapangan. Lihat juga halaman "buku masak" tentang formulir .

Hackish? cara , $ perhatikan ng-model di pengontrol Anda:

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

Pengontrol:

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

Cara terbaik , gunakan $ parser sebagai direktif. Saya tidak akan mengulangi jawaban yang sudah bagus yang diberikan oleh @ pkozlowski.opensource, jadi inilah tautannya: https://stackoverflow.com/a/14425022/215945

Semua solusi di atas melibatkan penggunaan ng-model, yang membuat pencarian thistidak perlu.

Menggunakan ng-change akan menimbulkan masalah. Lihat AngularJS - reset $ scope.value tidak mengubah nilai di templat (perilaku acak)

Mark Rajcok
sumber
Akhirnya membuat arahan! Terima kasih telah menyertakan cara terbaik. Butuh sedikit riset tetapi saya belajar banyak!
Chris Bier
1
Adakah yang bisa mengembangkan sisi negatifnya ke cara "mudah" yang dicantumkan terlebih dahulu (type = "number"), khususnya dibandingkan dengan cara "terbaik" yang disarankan ($ parser dalam direktif)?
Matt Welch
2
@MattWelch, Jawaban terlambat tetapi sisi negatifnya adalah dukungan browser. Juga di Chrome setidaknya, type=numbersecara otomatis akan menampilkan pemintal yang mungkin tidak diinginkan. Anda dapat menyembunyikan spinner melalui css, tetapi itu mungkin tidak berfungsi di semua browser.
Rosdi Kasim
4
Hanya dua hal yang mungkin bermasalah dengan pendekatan "mudah" (type = "number") yang 1. type = "number" memungkinkan tanda negatif (-), pemisah desimal (./,) dan notasi eksponensial (e) dan 2. pada perangkat seluler samsung Anda tidak dapat memasukkan angka negatif di bidang type = "number" (hanya tidak ada tombol minus di keyboard)
Ajudan
cara mudah ... firefox memungkinkan karakter dimasukkan ke dalam bidang angka saja. Itu tidak memperbarui model, tetapi menampilkan karakter
DRaehal
66

Menggunakan ng-patterndi bidang teks:

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

Kemudian masukkan ini ke pengontrol Anda

$scope.onlyNumbers = /^\d+$/;
MarkJ
sumber
Inilah yang akhirnya saya lakukan berdasarkan jawaban Marks, terima kasih atas contohnya! Saya yakin itu akan membantu seseorang!
Chris Bier
2
ini bekerja hampir sempurna, tetapi masih memungkinkan 'e' untuk dimasukkan.
cookie
Sangat membantu jika Anda berjuang dengan membatasi type = "number" dan panjangnya. Solusinya adalah dengan menggunakan pola-ng ini dan kembali ke type = "text". Solusi yang sangat rapi dan menghilangkan beban pemeriksaan kode untuk ng-change atau ng-keypress. Solusi ini tidak mengizinkan 'e' dimasukkan jadi saya berasumsi itu masalah lain.
PeterS
1
Tampak bagi saya sebagai browser khusus, apakah itu tidak akan mengizinkan entri numerik atau tidak. Di Chrome, cukup menggunakan <input type = 'number' /> sudah cukup dan tidak akan mengizinkan entri numerik apa pun, Firefox di sisi lain dengan Html yang sama akan mengizinkan input apa pun tetapi memicu bendera input yang tidak valid jika nilainya bukan numerik. Saya mencari cara sederhana untuk mendapatkan perilaku Chrome di semua browser
steve
19

Tidak ada solusi yang diusulkan yang bekerja dengan baik untuk saya, dan setelah beberapa jam saya akhirnya menemukan jalannya.

Ini adalah arahan sudut:

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

Dan masukannya akan terlihat seperti:

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

Ekspresi reguler mengevaluasi tombol yang ditekan, bukan nilainya .

Ia juga bekerja sempurna dengan masukan type="number"karena mencegah dari mengubah nilainya, sehingga kuncinya tidak pernah ditampilkan dan tidak mengacaukan model.

ragnar
sumber
Untuk mengizinkan negatif,restrict-to="[0-9\-]"
Noumenon
18

Inilah implementasi saya dari $parsersolusi yang direkomendasikan @Mark Rajcok sebagai metode terbaik. Ini pada dasarnya adalah $ parser yang sangat baik dari @ pkozlowski.opensource untuk jawaban teks tetapi ditulis ulang untuk hanya mengizinkan numerik. Semua pujian diberikan kepadanya, ini hanya untuk menghemat 5 menit membaca jawaban itu dan kemudian menulis ulang jawaban Anda sendiri:

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

Dan Anda akan menggunakannya seperti ini:

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

Menariknya, spasi tidak pernah mencapai parser kecuali dikelilingi oleh alfanumerik, jadi Anda harus melakukannya .trim() sesuai kebutuhan. Juga, parser ini TIDAK berfungsi <input type="number">. Untuk beberapa alasan, non-numerik tidak pernah membuat ke parser di mana mereka akan dihapus, tetapi mereka lakukan membuatnya menjadi kontrol input itu sendiri.

Mordred
sumber
Ketika saya menerapkan ini, saya mendapat kesalahan JS jika model input diinisialisasi tanpa nilai. Membuat perubahan ini menyelesaikan bahwa: var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
Alkie
Terima kasih @Alkie. Saya menambahkan perubahan itu ke dalam arahan.
Mordred
1
Anda harus menyetel ng-trimuntuk falsememastikan spasi mencapai parser Anda.
Ilya
Untuk membuatnya sempurna Anda perlu menambahkan modelCtrl.$commitViewValue();antara $ setViewValue (clean); dan $ render ();
ingaham
1
Terima kasih! Ini luar biasa! Ini sangat membantu
iulial
4

Ada beberapa cara untuk melakukan ini.

Anda bisa menggunakan type="number":

<input type="number" />

Atau - Saya membuat arahan yang dapat digunakan kembali untuk ini yang menggunakan ekspresi reguler.

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;
                    }
                });
            }
        };
    }]);    
}());
Peter Rasmussen
sumber
gunakan, $ (element) .on ('input', function () {// logika Anda}); ini akan mencegah bahkan memasukkan nilai yang tidak diinginkan
Vishal
4

Berikut adalah solusi yang cukup bagus untuk membuat hanya izinkan masukkan nomor ke input:

<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
Raniys
sumber
ini tidak memungkinkan saya untuk menekan delete atau backspace
Ravistm
hapus dan backspace berfungsi. Diuji di Firefox 76.0.1
iamjoshua
3

Semua solusi di atas cukup besar, saya ingin memberikan 2 sen saya untuk ini.

Saya hanya memeriksa apakah nilai yang dimasukkan adalah angka atau tidak, dan memeriksa apakah tidak kosong, itu saja.

Ini html-nya:

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

Inilah JS:

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

Cukup sederhana.

Saya percaya ini tidak akan berhasil pada Tempel, asal diketahui saja.

Untuk Tempel, saya pikir Anda perlu menggunakan acara onChange dan mengurai seluruh string, binatang buas lain yang tamme. Ini khusus untuk mengetik.

UPDATE untuk Tempel : cukup tambahkan fungsi JS ini:

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

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

Dan input html menambahkan pemicu:

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

Saya harap ini membantu o /

Zorkind
sumber
2

Berikut ini adalah Plunker yang menangani situasi apa pun di atas proposisi tidak menangani.
Dengan menggunakan $ formatters dan $ parsers pipeline dan menghindari type = "number"

Dan berikut penjelasan masalah / solusinya (juga tersedia di 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)
 *
 */
gr3g
sumber
1
   <input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />

Anda dapat menggunakan atribut khusus numerik.

tahsin ilhan
sumber
1

DESIMAL

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

Digit

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

arahan sudut untuk memvalidasi nomor

Angeldev
sumber
0

Saya tahu ini sudah tua, tetapi saya telah membuat arahan untuk tujuan ini jika ada yang mencari solusi yang mudah. Sangat mudah digunakan.

Anda bisa memeriksanya di sini .

cohenadair
sumber
0

Anda mungkin juga ingin menghapus 0 di awal masukan ... Saya cukup menambahkan blok if ke jawaban Mordred di atas karena saya belum bisa memberikan komentar ...

  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;
          });
      }
    };
  })
sireken
sumber
0

Coba ini,

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

}
Joee
sumber
0

SOLUSI: Saya membuat arahan untuk semua input, angka, teks, atau apa pun, di aplikasi, sehingga Anda dapat memasukkan nilai dan mengubah acara. Buatlah sudut 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">
Seba Arce
sumber
-1

Saya akhirnya membuat arahan yang dimodifikasi dari kode di atas untuk menerima input dan mengubah format dengan cepat ...

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

})

sireken
sumber
-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>
Rahul Sharma
sumber
1
Kode dumping biasanya tidak disukai. Mohon tambahkan penjelasan.
rayryeng
1
untuk membatasi tekan tombol coba ini - - - nomor fungsi (evt) {var charCode = (evt.which)? evt.which: event.keyCode if (charCode> 31 && (charCode <48 || charCode> 57)) return false; kembali benar; <input type = "number" min = "0" onkeypress = "return Number (event)">
Rahul Sharma
-1

HTML dasar

<input type="number" />

Bootstrap dasar

<input class="form-control" type="number" value="42" id="my-id">
Amr Ibrahim
sumber
@Praveen saya tidak setuju dengan Anda, pertanyaannya tidak menyebutkan bootstrap apa pun. mengapa kami harus menyebutkan sesuatu yang tidak ada dalam pertanyaan?
Amr Ibrahim
jika kita ingin menggunakan bootstrap <input class="form-control" type="number" >
Amr Ibrahim