Я использую ngChange в AngularJS для запуска настраиваемой функции, которая удалит любые буквы, добавленные пользователем во ввод.
<input type="text" name="inputName" data-ng-change="numbersOnly()"/>
Проблема в том, что мне нужно настроить таргетинг на сработавший ввод, numbersOnly()
чтобы я мог удалить введенные буквы. Я долго и упорно на Google и не смог найти что - нибудь относительно этого.
Что я могу сделать?
javascript
angularjs
angularjs-directive
Крис Бир
источник
источник
Ответы:
Простой способ : используйте type = "number", если он подходит для вашего варианта использования:
<input type="number" ng-model="myText" name="inputName">
Еще один простой способ: ng-pattern также можно использовать для определения регулярного выражения, которое ограничивает то, что разрешено в поле. См. Также страницу "кулинарной книги" о формах .
Хакиш? Кстати , $ посмотрите ng-модель в вашем контроллере:
<input type="text" ng-model="myText" name="inputName">
Контроллер:
$scope.$watch('myText', function() { // put numbersOnly() logic here, e.g.: if ($scope.myText ... regex to look for ... ) { // strip out the non-numbers } })
Лучше всего использовать $ parser в директиве. Я не собираюсь повторять уже хороший ответ, предоставленный @ pkozlowski.opensource, поэтому вот ссылка: https://stackoverflow.com/a/14425022/215945
Все вышеперечисленные решения предполагают использование ng-модели, что делает поиск
this
ненужным.Использование ng-change вызовет проблемы. См. AngularJS - сброс $ scope.value не меняет значение в шаблоне (случайное поведение)
источник
type=number
будет автоматически отображаться счетчик, что может быть нежелательно. Вы можете скрыть счетчик через CSS, но, опять же, даже это может не работать во всех браузерах.Использование
ng-pattern
в текстовом поле:<input type="text" ng-model="myText" name="inputName" ng-pattern="onlyNumbers">
Затем включите это в свой контроллер
$scope.onlyNumbers = /^\d+$/;
источник
Ни одно из предложенных решений не помогло мне, и через пару часов я наконец нашел способ.
Это угловая директива:
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"
потому что предотвращает изменение его значения, поэтому ключ никогда не отображается и не влияет на модель.источник
restrict-to="[0-9\-]"
Вот моя реализация
$parser
решения, которое @Mark Rajcok рекомендует как лучший метод. По сути, это отличный синтаксический анализатор $ @ pkozlowski.opensource для текстового ответа, но переписанный, чтобы разрешать только числа. Вся заслуга ему, это просто для того, чтобы сэкономить 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">
. По какой-то причине нечисловые числа никогда не попадают в анализатор, откуда они будут удалены, но они попадают в сам элемент управления вводом.источник
var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
ng-trim
значение,false
чтобы пробелы доходили до вашего парсера.modelCtrl.$commitViewValue();
между $ setViewValue (clean); и $ render ();Есть несколько способов сделать это.
Вы можете использовать
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; } }); } }; }]); }());
источник
Вот довольно хорошее решение, позволяющее вводить только номер
input
:<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
источник
Все вышеперечисленные решения довольно большие, я хотел отдать на это свои 2 цента.
Я только проверяю, является ли введенное значение числом или нет, и проверяю, не пусто ли оно, вот и все.
Вот HTML:
<input type="text" ng-keypress="CheckNumber()"/>
Вот JS:
$scope.CheckKey = function () { if (isNaN(event.key) || event.key === ' ' || event.key === '') { event.returnValue = ''; } };
Все очень просто.
Я верю, что это не сработает на Paste tho, просто чтобы это было известно.
Для Paste, я думаю, вам нужно будет использовать событие onChange и проанализировать всю строку, совсем другое чудовище - tamme. Это характерно для набора текста.
ОБНОВЛЕНИЕ для вставки : просто добавьте эту функцию JS:
$scope.CheckPaste = function () { var paste = event.clipboardData.getData('text'); if (isNaN(paste)) { event.preventDefault(); return false; } };
И ввод html добавляет триггер:
<input type="text" ng-paste="CheckPaste()"/>
Надеюсь, это поможет o /
источник
Вот Plunker, который обрабатывает любую ситуацию, описанную выше.
Используя $ formatters и $ parsers pipeline и избегая 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) * */
источник
<input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />
вы можете использовать только числовой атрибут.
источник
ДЕСЯТИЧНЫЙ
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); } }; });
angular директивы для проверки чисел
источник
Я знаю, что это устарело, но я создал директиву для этой цели на случай, если кто-то ищет простое решение. Очень просто использовать.
Вы можете проверить это здесь .
источник
вы также можете удалить 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 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(); } }
источник
РЕШЕНИЕ: я делаю директиву для всех входов, числа, текста или любого другого в приложении, чтобы вы могли ввести значение и изменить событие. Сделайте для углового 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">
источник
В итоге я создал измененную директиву приведенного выше кода, чтобы принимать ввод и изменять формат на лету ...
.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>
источник
Базовый HTML
<input type="number" />
Базовый бутстрап
<input class="form-control" type="number" value="42" id="my-id">
источник
<input class="form-control" type="number" >