Как ограничить ввод только цифрами?
Я использую ngChange в AngularJS, чтобы вызвать пользовательскую функцию, которая удалит любые буквы, которые пользователь добавляет на вход.
<input type="text" name="inputName" data-ng-change="numbersOnly()"/>
проблема в том, что мне нужно нацелиться на вход, который вызвал numbersOnly() Так что я могу удалить введенные буквы. Я долго и упорно смотрел на Google и не смог найти ничего по этому поводу.
что я могу сделать?
15 ответов:
легко используйте type= "number" если это работает для вашего случая использовать:
<input type="number" ng-model="myText" name="inputName">еще один простой способ: ng-pattern также можно использовать для определения регулярного выражения, которое будет ограничивать то, что разрешено в поле. Смотрите также раздел страница "поваренная книга" о формах.
программистские? путь, $смотреть ng-модель в контроллере:
<input type="text" ng-model="myText" name="inputName">
используя
ng-patternв текстовом поле:<input type="text" ng-model="myText" name="inputName" ng-pattern="onlyNumbers">затем включите это на вашем контроллере
$scope.onlyNumbers = /^\d+$/;
вот моя реализация
$parserрешение, которое @Mark Rajcok рекомендует как лучший метод. Это, по сути, @pkozlowski. отличный $ парсер для текстового ответа но переписано только для того, чтобы разрешить цифры. Вся заслуга идет к нему, это просто, чтобы сэкономить вам 5 минут чтения этого ответа, а затем переписать свой собственный: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; }); } }; });и вы бы использовали его так:
<input type="text" name="number" ng-model="num_things" numeric-only>интересно, что пробелы никогда не достигают парсера, если не окружены буквенно-цифровой, так что вам придется
.trim()по мере необходимости. Кроме того, этот парсер делает не работы на<input type="number">. По какой-то причине нечисловые никогда не попадают в парсер, где они будут удалены, но они do сделать это в самом элементе управления входом.
ни одно из предложенных решений работал для меня, и спустя пару часов я наконец нашел способ.
Это угловая директива:
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(); } }); } } });и вход будет выглядеть так:
<input type="number" min="0" name="inputName" ng-model="myModel" restrict-to="[0-9]">регулярное выражение оценивает нажатую клавишу, а не значение.
Он также отлично работает с входов
type="number"потому что предотвращает от изменения его значения, так что ключ никогда не отображается и он не возиться с модель.
есть несколько способов сделать это.
вы могли бы использовать
type="number":<input type="number" />альтернативно-я создал многоразовый директива для этого используется регулярное выражение.
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; } }); } }; }]); }());
здесь Plunker обработка любой ситуации выше предложения не обрабатывать.
Используя конвейер $formatters и $parsers и избегая type= "number"и вот объяснение проблем / решений (также доступно в 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) * */
DECIMAL
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); } }; });цифры
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); } }; });
Я знаю, что это старый, но я создал директиву для этой цели в случае, если кто ищет простое решение. Очень проста в использовании.
вы можете проверить это здесь.
вы также можете удалить 0 в начале ввода... Я просто добавляю блок if к ответу Мордреда выше, потому что я еще не могу сделать комментарий...
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; }); } }; })
<input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />вы можете использовать только числовых атрибутов .
вот довольно хорошее решение, чтобы сделать только разрешить ввести номер в
input:<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
попробуйте это,
<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(); } }
Я закончил тем, что создал модифицированную директиву вышеуказанного кода, чтобы принять ввод и изменить формат на лету...
.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(); } } }); } };})
<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>
Comments