如何只允许input一个数字(数字和小数点)?

我是angularjs的新手。 我想知道什么是只允许一个有效的数字input到一个文本框的方式。 例如,用户可以input“1.25”,但不能input“1.a”或“1 ..”。 当用户尝试input下一个字符时,会使其成为无效的数字,他无法input。

提前致谢。

您可以尝试使用此指令来阻止任何无效字符被input到input字段中。 ( 更新 :这依赖于具有明确的模型知识的指令,这对于可重用性并不理想,请参阅下面的可重用示例)

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

它也解释了这些情况:

  1. 从非空的有效string转换为空string
  2. 负值
  3. 负小数值

我在这里创build了一个jsFiddle ,所以你可以看到它是如何工作的。

UPDATE

遵循亚当·托马斯关于在指令中不直接包含模型引用(我认为这是最好的方法)的反馈,我已经更新了我的jsFiddle以提供一种不依赖于此的方法。

该指令使用本地作用域与父作用域的双向绑定 。 指令中对variables所做的更改将反映在父范围内,反之亦然。

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> 

angular码:

 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的好方法。 该指令目前只允许正整数,但正则expression式可以很容易地更新,以支持任何所需的数字格式。

我的指令很容易使用:

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

我想强调的是保持模型参考脱离指令是重要的。

我希望你觉得这有帮助。

非常感谢Sean Christe和Chris Grimes向我介绍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标记将最小可更改值设置为某个十进制数字:

例如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/

DEMO – – 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> 

注意:不要忘记包含带有angular度js的jQuery

有一个input号码指令,我相信可以做你想要的。

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

//types: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); } }; 

我想要一个指令,可以限制范围内的minmax属性如下所示:

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

这需要你包含angular色资源库持久绑定的字段进行validation。

工作示例在这里

像1.2.0-rc.3 +中的冠军一样工作。 修改正则expression式,你应该全部设置。 也许像/^(\d|\.)+$/ ? 一如既往,完成后validation服务器端。

这对我来说似乎是最简单的: 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; }); } }; }); 

我修改了Alan的答案,将数字限制在指定的最小/最大值。 如果input的数字超出范围,则会在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'); }); } }; }); 

从戈迪的回答扩大:

好工作btw。 但它也允许在前面。 这将删除它。

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

这里是一个衍生物,它也会阻止小数点input两次

HTML

  <input tabindex="1" type="text" placeholder="" name="salary" id="salary" data-ng-model="salary" numbers-only="numbers-only" required="required"> 

angular

  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(/[az!@#$%^&*()_+\-=\[\]{};':"\\|,<>\/?]/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; }); } }; }); 

扩展Adam Thomas答案可以通过添加input参数与自定义正则expression式轻松地使此指令更通用:

 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上

我有一个类似的问题,并更新input[type="number"]angular度docs作品与小数精度的作品,我用这种方法来解决它。

PS:一个快速提醒是,浏览器支持input[type =“number”]中的字符'e'和'E',因为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" /> 

这是与这个片段的运动员

请检查我的组件,这将帮助您只允许一个特定的数据types。 目前支持整数,小数,string和时间(HH:MM)。

  • string – string是可选的最大长度
  • integer – 整数只允许使用可选的最大值
  • decimal – 十进制只允许使用可选的小数点和最大值(默认为2个小数点)
  • time – 24小时只允许时间格式(HH:MM)

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

DIGITS

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

validation号码的angular度指令