Bir girişi yalnızca sayı kabul edecek şekilde nasıl kısıtlarım?


92

AngularJS'de, kullanıcının girdiye eklediği harfleri kaldıracak özel bir işlevi tetiklemek için ngChange kullanıyorum.

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

Sorun şu ki numbersOnly(), girilen harfleri kaldırabilmem için tetiklenen girişi hedeflemem gerekiyor . Google'da uzun uzun aradım ve bununla ilgili hiçbir şey bulamadım.

Ne yapabilirim?


Bu aynı zamanda harflerin girilmesine izin vermeyen iyi bir çözümdür.
Himanshu Bhandari

Yanıtlar:


104

Kolay yolu , kullanım durumunuz için uygunsa type = "number" kullanın:

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

Başka bir kolay yol: ng-paterni , alanda izin verilenleri sınırlandıracak bir normal ifadeyi tanımlamak için de kullanılabilir. Formlarla ilgili "yemek kitabı" sayfasına da bakın .

Hackish? yol , $ denetleyicinizdeki ng modelini izleyin:

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

Denetleyici:

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

En iyi yol , bir yönergede bir $ ayrıştırıcı kullanmaktır. @ Pkozlowski.opensource tarafından sağlanan zaten iyi olan yanıtı tekrar etmeyeceğim, işte bağlantı: https://stackoverflow.com/a/14425022/215945

Yukarıdaki çözümlerin tümü, bulmayı thisgereksiz kılan ng modelini kullanmayı içerir .

Ng-değişiminin kullanılması sorunlara neden olacaktır. Bkz. AngularJS - $ kapsam.value'nun sıfırlanması şablondaki değeri değiştirmez (rastgele davranış)


Bir yönerge oluşturmakla sona erdi! En iyi yolu dahil ettiğiniz için teşekkürler. Biraz araştırma yaptım ama çok şey öğrendim!
Chris Bier

1
Olumsuz yönlerini, özellikle önerilen "en iyi" yoldan (yönergede $ ayrıştırıcı) önce listelenen "kolay" yola (tür = "sayı") genişletebilen var mı?
Matt Welch

2
@MattWelch, Geç cevap ancak olumsuz yanı tarayıcı desteğidir. Ayrıca en azından Chrome'da, type=numberistenmeyen olabilecek döndürücüyü otomatik olarak gösterecektir. Spinner'ı css ile gizleyebilirsiniz, ancak daha sonra bu bile tüm tarayıcılarda çalışmayabilir.
Rosdi Kasım

4
"Kolay" (tür = "sayı") yaklaşımıyla sorunlu olabilecek iki şey, 1. tür = "sayı" nın negatif işarete (-), ondalık ayırıcıya (./,) ve üstel gösterime (e) izin vermesidir. samsung mobil cihazlarda 2. (sadece hayır eksi klavyede tuş vardır) bir tip = "sayı" alanını negatif bir sayı giremezsiniz
Yardımcıları

kolay yol ... firefox, karakterlerin yalnızca sayı alanına girilmesine izin verir. Modeli güncellemez, ancak karakterleri gösterir
DRaehal

66

ng-patternMetin alanında kullanma :

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

Ardından bunu kontrol cihazınıza ekleyin

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

Bu, Marks yanıtına dayanarak yaptığım şeydi, yine de örnekler için teşekkürler! Eminim birine yardım edecek!
Chris Bier

2
bu neredeyse mükemmel çalışır, ancak yine de "e" nin girilmesine izin verir.
çerezler

Type = "number" ve uzunluğu sınırlamasıyla uğraşıyorsanız gerçekten yardımcı olur. Çözüm, bu ng-desenini kullanmak ve tip = "metin" e geri dönmektir. Çok derli toplu çözüm ve ng-değiştirme veya ng-tuşa basma için kod kontrolü yükünü ortadan kaldırır. Bu çözüm 'e'lerin girilmesine izin vermedi, bu yüzden bunun başka bir sorun olduğunu varsayıyorum.
PeterS

1
Bana hiçbir sayısal girişe izin verip vermeyeceği konusunda tarayıcıya özgü gibi görünüyor. Chrome'da sadece <input type = 'number' /> kullanmak yeterlidir ve herhangi bir sayısal girişe izin vermez, diğer yandan aynı Html'ye sahip Firefox herhangi bir girişe izin verir ancak değer sayısal değilse geçersiz giriş bayrağını tetikler. Tüm tarayıcılarda Chrome davranışını elde etmenin basit bir yolunu arıyorum
steve

19

Önerilen çözümlerin hiçbiri benim için işe yaramadı ve birkaç saat sonra sonunda yolu buldum.

Bu açısal yönerge:

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

Ve girdi şöyle görünecektir:

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

Normal ifade , değeri değil, basılan tuşu değerlendirir .

Aynı zamanda girdilerle de mükemmel çalışır type="number"çünkü değerinin değiştirilmesini engeller, böylece anahtar hiçbir zaman gösterilmez ve modelle uğraşmaz .


Negatiflere izin vermek için,restrict-to="[0-9\-]"
Noumenon

18

İşte $parser@Mark Rajcok'un en iyi yöntem olarak önerdiği çözüm uygulamam . Aslında @ pkozlowski.opensource'un metin yanıtı için mükemmel $ ayrıştırıcısıdır, ancak yalnızca sayısallara izin vermek için yeniden yazılmıştır. Tüm övgü ona aittir, bu sadece 5 dakikalık o cevabı okuduktan sonra kendi cevabınızı yeniden yazmaktan tasarruf etmek içindir:

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

Ve bunu şu şekilde kullanırsın:

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

İlginç bir şekilde, bir alfasayısal ile çevrili olmadıkça boşluklar ayrıştırıcıya asla ulaşmaz, bu yüzden .trim()gerektiği gibi yapmanız gerekir. Ayrıca, bu ayrıştırıcı gelmez DEĞİL üzerinde çalışmak <input type="number">. Bazı nedenlerden dolayı, sayısal olmayanlar asla kaldırılacakları ayrıştırıcıya ulaşmazlar, ancak bunu giriş kontrolünün kendisine yaparlar.


Bunu uyguladığımda, girdinin modeli bir değer olmadan başlatıldıysa JS hataları alıyorum. Bu değişiklik çözüldü yapma o: var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
Alkie

Teşekkürler @Alkie. Bu değişikliği direktife ekledim.
Mordred

1
Sen ayarlamak zorunda ng-trimiçin falseemin alanlarda sizin ayrıştırıcı ulaşmak yapmak.
Ilya

Mükemmel hale getirmek modelCtrl.$commitViewValue();için $ setViewValue (clean); ve $ render ();
ingaham

1
Teşekkür ederim! Bu harika! Çok yardımcı oldu
iulial

4

Bunu yapmanın birkaç yolu var.

Şunları kullanabilirsiniz type="number":

<input type="number" />

Alternatif olarak - Bunun için düzenli ifade kullanan yeniden kullanılabilir bir yönerge oluşturdum .

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

$ (element) .on ('input', function () {// mantığınız}); bu istenmeyen değerin girilmesini bile engelleyecektir
Vishal

4

Burada, yalnızca sayı girilmesine izin vermek için oldukça iyi bir çözüm input:

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

bu sil veya geri al tuşuna
basmama

delete ve backspace yine de çalışır. Firefox 76.0.1'de test edildi
iamjoshua

3

Yukarıdaki tüm çözümler oldukça büyük, bunun üzerine 2 sentimi vermek istedim.

Sadece girilen değerin bir sayı olup olmadığını ve boş olup olmadığını kontrol ediyorum, hepsi bu.

İşte html:

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

İşte JS:

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

Oldukça basit.

Bunun Paste tho üzerinde çalışmayacağına inanıyorum, sadece biliniyor.

Yapıştır için, onChange olayını kullanmanız ve tüm dizeyi ayrıştırmanız gerektiğini düşünüyorum, tamme başka bir canavar. Bu, yazmaya özeldir.

Yapıştır için GÜNCELLEME : bu JS işlevini eklemeniz yeterlidir:

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

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

Ve html girişi tetikleyiciyi ekler:

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

Umarım bu yardımcı olur


2

İşte bir Plunker yukarıdaki önermenin üstesinden gelmeyen herhangi bir durumu ele alıyor.
$ Formatters ve $ ayrıştırıcı ardışık düzen kullanarak ve type = "number" kullanmaktan kaçınarak

Ve işte problemlerin / çözümlerin açıklaması (Plunker'da da mevcuttur):

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

yalnızca sayısal özniteliği kullanabilirsiniz.


1

ONDALIK

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

RAKAMLAR

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

sayıları doğrulamak için açısal yönergeler


0

Bunun eski olduğunu biliyorum, ancak herhangi birinin kolay bir çözüm araması durumunda bu amaçla bir yönerge oluşturdum. Kullanımı çok basit.

Buradan kontrol edebilirsiniz .


0

Girişin başında 0'ı da kaldırmak isteyebilirsiniz ... Yukarıdaki Mordred cevabına sadece bir if bloğu ekliyorum çünkü henüz bir yorum yapamıyorum ...

  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

Bunu dene,

<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

ÇÖZÜM: Uygulamadaki tüm girişler, sayılar, metinler veya herhangi biri için bir yönerge hazırlıyorum, böylece bir değer girebilir ve etkinliği değiştirebilirsiniz. Açısal 6 için yap

 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

Girişleri kabul etmek ve formatı anında değiştirmek için yukarıdaki kodun değiştirilmiş bir yönergesini oluşturdum ...

.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
Kod dökümü genellikle hoş karşılanmaz. Lütfen biraz açıklama ekleyin.
rayryeng

1
kısıtlama anahtarı için şunu deneyin - - - function Number (evt) {var charCode = (evt.which)? evt.which: event.keyCode if (charCode> 31 && (charCode <48 || charCode> 57)) false döndürür; doğruya dön; <input type = "number" min = "0" onkeypress = "return Number (event)">
Rahul Sharma,

-1

Temel HTML

<input type="number" />

Temel önyükleme

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

@Praveen Sana katılmıyorum, soru herhangi bir önyüklemeden bahsetmiyor. Neden soruda olmayan bir şeyden bahsetmeliyiz?
Amr Ibrahim

bootstrap kullanmak istiyorsak <input class="form-control" type="number" >
Amr Ibrahim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.