Làm cách nào để hạn chế đầu vào chỉ chấp nhận các số?


92

Tôi đang sử dụng ngChange trong AngularJS để kích hoạt một chức năng tùy chỉnh sẽ xóa bất kỳ ký tự nào mà người dùng thêm vào đầu vào.

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

Vấn đề là tôi cần nhắm mục tiêu đầu vào được kích hoạt numbersOnly()để tôi có thể xóa các ký tự đã nhập. Tôi đã tìm kiếm rất lâu và chăm chỉ trên Google và không thể tìm thấy bất cứ điều gì liên quan đến điều này.

Tôi có thể làm gì?


Đây cũng là một giải pháp tốt, không cho phép nhập các chữ cái.
Himanshu Bhandari

Câu trả lời:


104

Cách dễ dàng , hãy sử dụng type = "number" nếu nó phù hợp với trường hợp sử dụng của bạn:

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

Một cách dễ dàng khác: ng-pattern cũng có thể được sử dụng để xác định một regex sẽ giới hạn những gì được phép trong trường. Xem thêm trang "sách dạy nấu ăn" về các biểu mẫu .

Tàn sát? cách , $ xem ng-model trong bộ điều khiển của bạn:

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

Bộ điều khiển:

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

Cách tốt nhất , hãy sử dụng $ parser trong một chỉ thị. Tôi sẽ không lặp lại câu trả lời đã được cung cấp bởi @ pkozlowski.opensource, vì vậy đây là liên kết: https://stackoverflow.com/a/14425022/215945

Tất cả các giải pháp trên đều liên quan đến việc sử dụng ng-model, khiến việc tìm kiếm thiskhông cần thiết.

Sử dụng ng-change sẽ gây ra vấn đề. Xem AngularJS - đặt lại $ scope.value không thay đổi giá trị trong mẫu (hành vi ngẫu nhiên)


Đã kết thúc việc tạo chỉ thị! Cảm ơn vì đã bao gồm cách tốt nhất. Có một chút nghiên cứu nhưng tôi đã học được rất nhiều!
Chris Bier

1
Bất cứ ai có thể mở rộng nhược điểm của cách "dễ dàng" được liệt kê đầu tiên (type = "number"), đặc biệt là so với cách "tốt nhất" được đề xuất ($ parser trong chỉ thị)?
Matt Welch

2
@MattWelch, Câu trả lời muộn nhưng nhược điểm là hỗ trợ trình duyệt. Cũng trong Chrome ít nhất, type=numbersẽ tự động hiển thị spinner có thể không mong muốn. Bạn có thể ẩn spinner qua css nhưng sau đó, thậm chí nó có thể không hoạt động trên tất cả các trình duyệt.
Rosdi Kasim

3
Chỉ có hai điều có thể có vấn đề với phương pháp tiếp cận "dễ dàng" (type = "number") là 1. type = "number" cho phép dấu âm (-), dấu phân tách thập phân (./,) và ký hiệu mũ (e) và 2. trên thiết bị di động của samsung, bạn không thể nhập số âm trong trường type = "number" (không có phím trừ trên bàn phím)
Aides

cách dễ dàng ... firefox cho phép các ký tự được nhập vào một trường chỉ số. Nó không cập nhật mô hình, nhưng hiển thị các ký tự
DRaehal

66

Sử dụng ng-patterntrên trường văn bản:

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

Sau đó đưa nó vào bộ điều khiển của bạn

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

Đây là những gì tôi đã kết thúc dựa trên câu trả lời của Marks, cảm ơn vì các ví dụ! Tôi chắc rằng nó sẽ giúp ích cho ai đó!
Chris Bier

2
điều này hoạt động gần như hoàn hảo, nhưng vẫn cho phép nhập 'e'.
cookie

Thực sự hữu ích nếu bạn đang gặp khó khăn với việc giới hạn type = "number" và độ dài của nó. Giải pháp là sử dụng ng-pattern này và hoàn nguyên về type = "text". Giải pháp rất gọn gàng và loại bỏ khối lượng kiểm tra mã cho ng-change hoặc ng-keypress. Giải pháp này không cho phép nhập 'e's nên tôi cho rằng đó là một vấn đề khác.
PeterS

1
Có vẻ như đối với tôi là trình duyệt cụ thể về việc liệu nó có cho phép không có mục nhập số hay không. Trên Chrome chỉ cần sử dụng <input type = 'number' /> là đủ và nó sẽ không cho phép bất kỳ mục nhập nào không có số, mặt khác, Firefox với cùng một Html sẽ cho phép bất kỳ đầu vào nào nhưng kích hoạt cờ nhập không hợp lệ nếu giá trị không phải là số. Tôi đang tìm một cách đơn giản để có được hoạt động của Chrome trên tất cả các trình duyệt
steve

19

Không có giải pháp nào được đề xuất phù hợp với tôi, và sau vài giờ, cuối cùng tôi đã tìm ra cách.

Đây là chỉ thị góc:

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

Và đầu vào sẽ giống như sau:

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

Biểu thức chính quy đánh giá phím được nhấn, không phải giá trị .

Nó cũng hoạt động hoàn hảo với các đầu vào type="number"vì ngăn không cho thay đổi giá trị của nó, vì vậy khóa không bao giờ được hiển thị và nó không gây rối với mô hình.


Để cho phép phủ định,restrict-to="[0-9\-]"
Noumenon

18

Đây là cách tôi triển khai $parsergiải pháp mà @Mark Rajcok đề xuất là phương pháp tốt nhất. Về cơ bản, nó là trình phân tích cú pháp $ tuyệt vời của @ pkozlowski.opensource cho câu trả lời văn bản nhưng được viết lại để chỉ cho phép các số. Tất cả tín dụng đều thuộc về anh ấy, điều này chỉ để bạn tiết kiệm 5 phút đọc câu trả lời đó và sau đó viết lại câu trả lời của riêng bạn:

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

Và bạn sẽ sử dụng nó như thế này:

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

Điều thú vị là các dấu cách không bao giờ đến được trình phân tích cú pháp trừ khi được bao quanh bởi chữ và số, vì vậy bạn phải làm .trim()như vậy nếu cần. Ngoài ra, trình phân tích cú pháp này KHÔNG hoạt động <input type="number">. Vì một số lý do, các số không phải số không bao giờ đến trình phân tích cú pháp nơi chúng sẽ bị xóa, nhưng chúng tự đưa nó vào điều khiển đầu vào.


Khi tôi triển khai điều này, tôi gặp lỗi JS nếu mô hình của đầu vào được khởi tạo mà không có giá trị. Thực hiện thay đổi này đã giải quyết được điều đó: var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
Alkie

Cảm ơn @Alkie. Tôi đã thêm thay đổi đó vào chỉ thị.
Mordred

1
Bạn phải đặt ng-trimđể falseđảm bảo các khoảng trắng tiếp cận trình phân tích cú pháp của bạn.
Ilya,

Để làm cho nó trở nên hoàn hảo, bạn cần thêm modelCtrl.$commitViewValue();vào giữa $ setViewValue (clean); và $ render ();
ingaham

1
Cảm ơn bạn! Điều này thật tuyệt vời! Nó đã giúp rất nhiều
iulial

4

Có một số cách để làm điều này.

Bạn có thể sử dụng type="number":

<input type="number" />

Ngoài ra - tôi đã tạo một chỉ thị có thể sử dụng lại cho điều này sử dụng biểu thức chính quy.

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 () {// your logic}); điều này sẽ ngăn chặn thậm chí nhập giá trị không mong muốn
Vishal

4

Đây là một giải pháp khá tốt để thực hiện chỉ cho phép nhập số vào input:

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

điều này không cho phép tôi nhấn xóa hoặc xóa lùi
Ravistm

xóa và xóa lùi hoạt động mặc dù. Đã thử nghiệm trên Firefox 76.0.1
iamjoshua

3

Tất cả các giải pháp trên đều khá lớn, tôi muốn tặng 2 xu cho điều này.

Tôi chỉ kiểm tra xem giá trị được đưa vào có phải là một số hay không và kiểm tra nếu nó không trống, vậy thôi.

Đây là html:

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

Đây là JS:

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

Nó khá đơn giản.

Tôi tin rằng điều này sẽ không hoạt động trên Paste tho, chỉ để nó được biết đến.

Đối với Dán, tôi nghĩ bạn sẽ cần sử dụng sự kiện onChange và phân tích cú pháp toàn bộ chuỗi, một con thú khác là tamme. Điều này dành riêng cho việc đánh máy.

CẬP NHẬT cho Dán : chỉ cần thêm hàm JS này:

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

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

Và đầu vào html thêm trình kích hoạt:

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

Tôi hy vọng điều này sẽ giúp o /


2

Đây là một Plunker xử lý bất kỳ tình huống nào trên đề xuất không xử lý.
Bằng cách sử dụng đường dẫn $ formatters và $ parsers và tránh type = "number"

Và đây là lời giải thích về các vấn đề / giải pháp (cũng có sẵn trong 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)
 *
 */

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

bạn có thể sử dụng thuộc tính chỉ số.


1

QUYẾT ĐỊNH

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

SỐ

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

chỉ thị góc để xác thực số


0

Tôi biết điều này đã cũ, nhưng tôi đã tạo một chỉ thị cho mục đích này trong trường hợp bất kỳ ai đang tìm kiếm một giải pháp dễ dàng. Rất đơn giản để sử dụng.

Bạn có thể kiểm tra nó ở đây .


0

bạn cũng có thể muốn xóa số 0 ở đầu đầu vào ... Tôi chỉ cần thêm khối if vào câu trả lời Mordred ở trên vì tôi chưa thể đưa ra nhận xét ...

  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

Thử cái này,

<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

GIẢI PHÁP: Tôi thực hiện một chỉ thị cho tất cả các đầu vào, số, văn bản hoặc bất kỳ, trong ứng dụng, vì vậy bạn có thể nhập một giá trị và thay đổi sự kiện. Tạo cho góc 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

Tôi đã kết thúc việc tạo một chỉ thị đã sửa đổi của mã trên để chấp nhận đầu vào và thay đổi định dạng ngay lập tức ...

.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
Việc bán phá giá mã thường không được chấp nhận. Vui lòng thêm một số giải thích.
rayryeng

1
để nhấn phím hạn chế, hãy thử cái này - - - function Number (evt) {var charCode = (evt.which)? evt.which: event.keyCode if (charCode> 31 && (charCode <48 || charCode> 57)) return false; trả về true; <input type = "number" min = "0" onkeypress = "return Number (event)">
Rahul Sharma

-1

HTML cơ bản

<input type="number" />

Bootstrap cơ bản

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

@Praveen Tôi không đồng ý với bạn, câu hỏi không đề cập đến bất kỳ bootstrap nào. tại sao chúng ta nên đề cập đến điều gì đó không tồn tại trong câu hỏi?
Amr Ibrahim

nếu chúng ta muốn sử dụng bootstrap <input class="form-control" type="number" >
Amr Ibrahim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.