Как разрешить только число (цифры и десятичная точка) для ввода во вход?
Я новичок в angularjs. Мне интересно, как можно разрешить только допустимое число, введенное в текстовое поле.
Например, пользователь может ввести "1.25", но не может ввести " 1.A" или "1..". При попытке пользователя ввести следующий символ, который сделает его инвалидом, он не может ввести его.
спасибо заранее.
18 ответов:
вы можете попробовать эту директиву, чтобы остановить ввод любых недопустимых символов в поле ввода. (обновление: это зависит от директивы, имеющей явное знание модели, которая не идеальна для повторного использования, см. ниже для повторного использования пример)
app.directive('isNumber', function () { return { require: 'ngModel', link: function (scope) { scope.$watch('wks.number', function(newValue,oldValue) { var arr = String(newValue).split(""); if (arr.length === 0) return; if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.' )) return; if (arr.length === 2 && newValue === '-.') return; if (isNaN(newValue)) { scope.wks.number = oldValue; } }); } }; });Он также учитывает эти сценарии:
- переход от непустой допустимой строки к пустой строке
- отрицательные значения
- отрицательное десятичное число значения
Я создал jsFiddle здесь вы можете увидеть, как это работает.
обновление
после обратной связи Адама Томаса относительно не включения ссылок на модели непосредственно внутри директивы (что я также считаю лучшим подходом) я обновил свой jsFiddle чтобы обеспечить метод, который не полагается на это.
директива использует двунаправленная привязка of локальная область для родительской области. Изменения переменных внутри директивы будут отражены в родительской области, и наоборот.
HTML:
<form ng-app="myapp" name="myform" novalidate> <div ng-controller="Ctrl"> <number-only-input input-value="wks.number" input-name="wks.name"/> </div> </form>Угловое код:
var app = angular.module('myapp', []); app.controller('Ctrl', function($scope) { $scope.wks = {number: 1, name: 'testing'}; }); app.directive('numberOnlyInput', function () { return { restrict: 'EA', template: '<input name="{{inputName}}" ng-model="inputValue" />', scope: { inputValue: '=', inputName: '=' }, link: function (scope) { scope.$watch('inputValue', function(newValue,oldValue) { var arr = String(newValue).split(""); if (arr.length === 0) return; if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.' )) return; if (arr.length === 2 && newValue === '-.') return; if (isNaN(newValue)) { scope.inputValue = oldValue; } }); } }; });
Я написал рабочий пример CodePen чтобы продемонстрировать отличный способ фильтрации числового ввода пользователя. В настоящее время директива допускает только положительные целые числа, но регулярное выражение может быть легко обновлено для поддержки любого желаемого числового формата.
моя директива проста в использовании:
<input type="text" ng-model="employee.age" valid-number />директива очень проста для понимания:
var app = angular.module('myApp', []); app.controller('MainCtrl', function($scope) { }); app.directive('validNumber', function() { return { require: '?ngModel', link: function(scope, element, attrs, ngModelCtrl) { if(!ngModelCtrl) { return; } ngModelCtrl.$parsers.push(function(val) { if (angular.isUndefined(val)) { var val = ''; } var clean = val.replace( /[^0-9]+/g, ''); if (val !== clean) { ngModelCtrl.$setViewValue(clean); ngModelCtrl.$render(); } return clean; }); element.bind('keypress', function(event) { if(event.keyCode === 32) { event.preventDefault(); } }); } }; });Я хочу подчеркнуть, что сохранение ссылок на модели из директивы является важный.
Я надеюсь, вы найдете это полезным.
большое спасибо Шон Кристи и Крис Граймс за то, что познакомил меня с ngModelController
прежде всего Большое спасибо Адам Томас Я использовал ту же логику Адама для этого с небольшой модификацией, чтобы принять десятичные значения.
Примечание: это позволит цифры только с 2 десятичными значениями
вот мой Пример Работающего
HTML
<input type="text" ng-model="salary" valid-number />Javascript
var app = angular.module('myApp', []); app.controller('MainCtrl', function($scope) { }); app.directive('validNumber', function() { return { require: '?ngModel', link: function(scope, element, attrs, ngModelCtrl) { if(!ngModelCtrl) { return; } ngModelCtrl.$parsers.push(function(val) { if (angular.isUndefined(val)) { var val = ''; } var clean = val.replace(/[^0-9\.]/g, ''); var decimalCheck = clean.split('.'); if(!angular.isUndefined(decimalCheck[1])) { decimalCheck[1] = decimalCheck[1].slice(0,2); clean =decimalCheck[0] + '.' + decimalCheck[1]; } if (val !== clean) { ngModelCtrl.$setViewValue(clean); ngModelCtrl.$render(); } return clean; }); element.bind('keypress', function(event) { if(event.keyCode === 32) { event.preventDefault(); } }); } }; });
используйте тег step, чтобы установить минимальное изменяемое значение для некоторого десятичного числа:
например, шаг="0.01"
<input type="number" step="0.01" min="0" class="form-control" name="form_name" id="your_id" placeholder="Please Input a decimal number" required>здесь есть некоторые документы по этому поводу:
http://blog.isotoma.com/2012/03/html5-input-typenumber-and-decimalsfloats-in-chrome/
демо - -jsFiddle
директива
.directive('onlyNum', function() { return function(scope, element, attrs) { var keyCode = [8,9,37,39,48,49,50,51,52,53,54,55,56,57,96,97,98,99,100,101,102,103,104,105,110]; element.bind("keydown", function(event) { console.log($.inArray(event.which,keyCode)); if($.inArray(event.which,keyCode) == -1) { scope.$apply(function(){ scope.$eval(attrs.onlyNum); event.preventDefault(); }); event.preventDefault(); } }); }; });HTML
<input type="number" only-num>Примечание : не забудьте включить jQuery с угловой js
есть директива input number, которая, как я верю, может делать только то, что вы хотите.
<input type="number" ng-model="{string}" [name="{string}"] [min="{string}"] [max="{string}"] [required] [ng-required="{string}"] [ng-minlength="{number}"] [ng-maxlength="{number}"] [ng-pattern="{string}"] [ng-change="{string}"]>официальный документ здесь:http://docs.angularjs.org/api/ng.directive:input.number
вы можете легко использовать ng-шаблон.
ng-pattern="/^[1-9][0-9]{0,2}(?:,?[0-9]{3}){0,3}(?:\.[0-9]{1,2})?$/"
HTML
<input type="text" name="number" only-digits>// просто введите 123
.directive('onlyDigits', 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 !== val) { ctrl.$setViewValue(digits); ctrl.$render(); } return parseInt(digits,10); } return undefined; } ctrl.$parsers.push(inputValue); } };/ / тип: 123 или 123.45
.directive('onlyDigits', 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 !== val) { ctrl.$setViewValue(digits); ctrl.$render(); } return parseFloat(digits); } return undefined; } ctrl.$parsers.push(inputValue); } };
Я хотел директиву, которая может быть ограничена в диапазоне
minиmaxатрибуты, как так:
<input type="text" integer min="1" max="10" />поэтому я написал следующее:
.directive('integer', function() { return { restrict: 'A', require: '?ngModel', link: function(scope, elem, attr, ngModel) { if (!ngModel) return; function isValid(val) { if (val === "") return true; var asInt = parseInt(val, 10); if (asInt === NaN || asInt.toString() !== val) { return false; } var min = parseInt(attr.min); if (min !== NaN && asInt < min) { return false; } var max = parseInt(attr.max); if (max !== NaN && max < asInt) { return false; } return true; } var prev = scope.$eval(attr.ngModel); ngModel.$parsers.push(function (val) { // short-circuit infinite loop if (val === prev) return val; if (!isValid(val)) { ngModel.$setViewValue(prev); ngModel.$render(); return prev; } prev = val; return val; }); } }; });
вот мой очень быстрый и грязный:
<!-- HTML file --> <html ng-app="num"> <head></head> <body ng-controller="numCtrl"> <form class="digits" name="digits" ng-submit="getGrades()" novalidate > <input type="text" placeholder="digits here plz" name="nums" ng-model="nums" required ng-pattern="/^(\d)+$/" /> <p class="alert" ng-show="digits.nums.$error.pattern">Numbers only, please.</p> <br> <input type="text" placeholder="txt here plz" name="alpha" ng-model="alpha" required ng-pattern="/^(\D)+$/" /> <p class="alert" ng-show="digits.alpha.$error.pattern">Text only, please.</p> <br> <input class="btn" type="submit" value="Do it!" ng-disabled="!digits.$valid" /> </form> </body> </html> // Javascript file var app = angular.module('num', ['ngResource']); app.controller('numCtrl', function($scope, $http){ $scope.digits = {}; });для этого необходимо включить библиотеку угловых ресурсов для постоянных привязок к полям в целях проверки.
работает как чемпион в 1.2.0-rc.3+. Изменить regex и вы должны быть все готово. Возможно, что-то вроде
/^(\d|\.)+$/? Как всегда, проверьте серверную сторону, когда вы закончите.
этот кажется мне самым простым: http://jsfiddle.net/thomporter/DwKZh/
(код не мой, я случайно наткнулся на него)
angular.module('myApp', []).directive('numbersOnly', function(){ return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function (inputValue) { // this next if is necessary for when using ng-required on your input. // In such cases, when a letter is typed first, this parser will be called // again, and the 2nd time, the value will be undefined if (inputValue == undefined) return '' var transformedInput = inputValue.replace(/[^0-9]/g, ''); if (transformedInput!=inputValue) { modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); } return transformedInput; }); } }; });
Я изменил ответ Алана выше, чтобы ограничить число до указанного min / max. При вводе числа вне диапазона, он будет устанавливать минимальное или максимальное значение после 1500 МС. Если вы полностью очистите поле, это ничего не установить.
HTML:
<input type="text" ng-model="employee.age" min="18" max="99" valid-number />Javascript:
var app = angular.module('myApp', []); app.controller('MainCtrl', function($scope) {}); app.directive('validNumber', function($timeout) { return { require: '?ngModel', link: function(scope, element, attrs, ngModelCtrl) { if (!ngModelCtrl) { return; } var min = +attrs.min; var max = +attrs.max; var lastValue = null; var lastTimeout = null; var delay = 1500; ngModelCtrl.$parsers.push(function(val) { if (angular.isUndefined(val)) { val = ''; } if (lastTimeout) { $timeout.cancel(lastTimeout); } if (!lastValue) { lastValue = ngModelCtrl.$modelValue; } if (val.length) { var value = +val; var cleaned = val.replace( /[^0-9]+/g, ''); // This has no non-numeric characters if (val.length === cleaned.length) { var clean = +cleaned; if (clean < min) { clean = min; } else if (clean > max) { clean = max; } if (value !== clean || value !== lastValue) { lastTimeout = $timeout(function () { lastValue = clean; ngModelCtrl.$setViewValue(clean); ngModelCtrl.$render(); }, delay); } // This has non-numeric characters, filter them out } else { ngModelCtrl.$setViewValue(lastValue); ngModelCtrl.$render(); } } return lastValue; }); element.bind('keypress', function(event) { if (event.keyCode === 32) { event.preventDefault(); } }); element.on('$destroy', function () { element.unbind('keypress'); }); } }; });
у меня была аналогичная проблема и обновить
input[type="number"]пример угловых документов для работы с точностью до десятичных знаков, и я использую этот подход для его решения.PS: быстрое напоминание заключается в том, что браузеры поддерживают символы ' e 'и' E 'во входных данных[type= "number"], потому что
keypressмероприятие обязательна.angular.module('numfmt-error-module', []) .directive('numbersOnly', function() { return { require: 'ngModel', scope: { precision: '@' }, link: function(scope, element, attrs, modelCtrl) { var currencyDigitPrecision = scope.precision; var currencyDigitLengthIsInvalid = function(inputValue) { return countDecimalLength(inputValue) > currencyDigitPrecision; }; var parseNumber = function(inputValue) { if (!inputValue) return null; inputValue.toString().match(/-?(\d+|\d+.\d+|.\d+)([eE][-+]?\d+)?/g).join(''); var precisionNumber = Math.round(inputValue.toString() * 100) % 100; if (!!currencyDigitPrecision && currencyDigitLengthIsInvalid(inputValue)) { inputValue = inputValue.toFixed(currencyDigitPrecision); modelCtrl.$viewValue = inputValue; } return inputValue; }; var countDecimalLength = function (number) { var str = '' + number; var index = str.indexOf('.'); if (index >= 0) { return str.length - index - 1; } else { return 0; } }; element.on('keypress', function(evt) { var charCode, isACommaEventKeycode, isADotEventKeycode, isANumberEventKeycode; charCode = String.fromCharCode(evt.which || event.keyCode); isANumberEventKeycode = '0123456789'.indexOf(charCode) !== -1; isACommaEventKeycode = charCode === ','; isADotEventKeycode = charCode === '.'; var forceRenderComponent = false; if (modelCtrl.$viewValue != null && !!currencyDigitPrecision) { forceRenderComponent = currencyDigitLengthIsInvalid(modelCtrl.$viewValue); } var isAnAcceptedCase = isANumberEventKeycode || isACommaEventKeycode || isADotEventKeycode; if (!isAnAcceptedCase) { evt.preventDefault(); } if (forceRenderComponent) { modelCtrl.$render(modelCtrl.$viewValue); } return isAnAcceptedCase; }); modelCtrl.$render = function(inputValue) { return element.val(parseNumber(inputValue)); }; modelCtrl.$parsers.push(function(inputValue) { if (!inputValue) { return inputValue; } var transformedInput; modelCtrl.$setValidity('number', true); transformedInput = parseNumber(inputValue); if (transformedInput !== inputValue) { modelCtrl.$viewValue = transformedInput; modelCtrl.$commitViewValue(); modelCtrl.$render(transformedInput); } return transformedInput; }); } }; });и в вашем html вы можете использовать этот подход
<input type="number" numbers-only precision="2" ng-model="model.value" step="0.10" />
расширение от ответа Горди:
хорошая работа кстати. Но это также позволило + спереди. Это позволит удалить его.
scope.$watch('inputValue', function (newValue, oldValue) { var arr = String(newValue).split(""); if (arr.length === 0) return; if (arr.length === 1 && (arr[0] == '-' || arr[0] === '.')) return; if (arr.length === 2 && newValue === '-.') return; if (isNaN(newValue)) { scope.inputValue = oldValue; } if (arr.length > 0) { if (arr[0] === "+") { scope.inputValue = oldValue; } } });
вот производная, которая также будет блокировать десятичную точку, которая будет введена дважды
HTML
<input tabindex="1" type="text" placeholder="" name="salary" id="salary" data-ng-model="salary" numbers-only="numbers-only" required="required">Угловое
var app = angular.module("myApp", []); app.directive('numbersOnly', function() { return { require : 'ngModel', link : function(scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function(inputValue) { if (inputValue == undefined) { return ''; //If value is required } // Regular expression for everything but [.] and [1 - 10] (Replace all) var transformedInput = inputValue.replace(/[a-z!@#$%^&*()_+\-=\[\]{};':"\|,<>\/?]/g, ''); // Now to prevent duplicates of decimal point var arr = transformedInput.split(''); count = 0; //decimal counter for ( var i = 0; i < arr.length; i++) { if (arr[i] == '.') { count++; // how many do we have? increment } } // if we have more than 1 decimal point, delete and leave only one at the end while (count > 1) { for ( var i = 0; i < arr.length; i++) { if (arr[i] == '.') { arr[i] = ''; count = 0; break; } } } // convert the array back to string by relacing the commas transformedInput = arr.toString().replace(/,/g, ''); if (transformedInput != inputValue) { modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); } return transformedInput; }); } }; });
расширение ответа Адама Томаса вы можете легко сделать эту директиву более универсальной, добавив входной аргумент с пользовательским регулярным выражением:
var app = angular.module('myApp', []); app.controller('MainCtrl', 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(); } }); } }});HTML
<input type="text" ng-model="employee.age" valid-input input-pattern="[^0-9]+" placeholder="Enter an age" /> </label>живу на CodePen
пожалуйста, проверьте мой компонент, который поможет вам разрешить только определенный тип данных. В настоящее время поддерживает целое число, десятичное число, строку и время(чч:мм).
string- строка допускается с дополнительной максимальной длинойinteger- целое число допускается только с необязательным максимальным значениемdecimal- Decimal разрешено только с дополнительными десятичными точками и максимальным значением (по умолчанию 2 десятичных точки)time- 24 часа формат времени (чч:мм) только разрешеноhttps://github.com/ksnimmy/txDataType
надеюсь, что это поможет.
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); } }; });
Comments