Como permitir que apenas um número (dígitos e ponto decimal) seja typescript em uma input?

Eu sou novo no angularjs. Eu estou querendo saber qual é a maneira de permitir apenas um número válido typescript em uma checkbox de texto. Por exemplo, o usuário pode digitar “1,25”, mas não pode digitar “1.a” ou “1 ..”. Quando o usuário tentar digitar o próximo caractere que o tornará inválido, ele não poderá digitá-lo.

Desde já, obrigado.

Você pode tentar esta diretiva para impedir que quaisquer caracteres inválidos sejam inseridos em um campo de input. ( Atualização : isso depende da diretiva ter conhecimento explícito do modelo, o que não é ideal para a reutilização, veja abaixo um exemplo reutilizável)

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

Também é responsável por esses cenários:

  1. Indo de uma string válida não vazia para uma string vazia
  2. Valores negativos
  3. Valores Decimais Negativos

Eu criei um jsFiddle aqui para você ver como funciona.

ATUALIZAR

Seguindo o feedback de Adam Thomas sobre não include referências de modelo diretamente dentro de uma diretiva (que eu também acredito ser a melhor abordagem) eu atualizei meu jsFiddle para fornecer um método que não depende disso.

A diretiva faz uso da binding bidirecional do escopo local ao escopo pai. As alterações feitas nas variables ​​dentro da diretiva serão refletidas no escopo pai e vice-versa.

HTML:

 

Código 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: '', 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; } }); } }; }); 

Escrevi um exemplo CodePen funcional para demonstrar uma ótima maneira de filtrar a input numérica do usuário. A diretiva atualmente permite somente inteiros positivos, mas a regex pode ser facilmente atualizada para suportar qualquer formato numérico desejado.

Minha diretiva é fácil de usar:

  

A diretiva é muito fácil de entender:

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

Quero enfatizar que manter as referências de modelo fora da diretiva é importante.

Eu espero que você ache isto útil.

Muito obrigado a Sean Christe e Chris Grimes por me apresentarem o ngModelController

Primeiro de tudo Big thanks to Adam thomas Eu usei a mesma lógica de Adam para isso com uma pequena modificação para aceitar os valores decimais.

Nota: Isso permitirá dígitos com apenas dois valores decimais

Aqui está o meu exemplo de trabalho

HTML

  

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

Use a tag step para definir o valor mínimo alterável para um número decimal:

eg passo = “0.01”

  

Há alguma documentação aqui:

http://blog.isotoma.com/2012/03/html5-input-typenumber-and-decimalsfloats-in-chrome/

DEMO – – jsFiddle

Directiva

  .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

   

Nota: Não se esqueça de include jQuery com js angular

Existe uma diretiva de número de input que acredito poder fazer exatamente o que você deseja.

  

o documento oficial está aqui: http://docs.angularjs.org/api/ng.directive:input.number

Você poderia facilmente usar o padrão ng.

 ng-pattern="/^[1-9][0-9]{0,2}(?:,?[0-9]{3}){0,3}(?:\.[0-9]{1,2})?$/" 

HTML

   

// Apenas digite 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); } }; 

// tipo: 123 ou 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); } }; 

Eu queria uma diretiva que pudesse ser limitada por atributos min e max forma:

então eu escrevi o seguinte:

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

Aqui está o meu realmente sujo-n-sujo:

     

Numbers only, please.


Text only, please.


// Javascript file var app = angular.module('num', ['ngResource']); app.controller('numCtrl', function($scope, $http){ $scope.digits = {}; });

Isso requer a inclusão da biblioteca de resources angulares para ligações persistentes nos campos para fins de validação.

Exemplo de trabalho aqui

Funciona como um campeão em 1.2.0-rc.3 +. Modifique o regex e você deve estar tudo pronto. Talvez algo como /^(\d|\.)+$/ ? Como sempre, valide o lado do servidor quando estiver pronto.

Este parece ser o mais fácil para mim: http://jsfiddle.net/thomporter/DwKZh/

(Código não é meu, eu acidentalmente tropecei nele)

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

Eu modifiquei a resposta de Alan acima para restringir o número ao min / max especificado. Se você inserir um número fora do intervalo, ele definirá o valor mínimo ou máximo após 1500 ms. Se você limpar o campo completamente, ele não irá definir nada.

HTML:

  

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

Eu tive um problema semelhante e atualizei o exemplo de input[type="number"] em documentos angulares para trabalhos com precisão de decimais e estou usando essa abordagem para resolvê-lo.

PS: Um lembrete rápido é que os navegadores suportam os caracteres ‘e’ e ‘E’ na input [type = “number”], porque o evento keypress é necessário.

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

E no seu html você pode usar essa abordagem

  

Aqui está o plunker com este trecho

Expandindo da resposta do gordy:

Bom trabalho. Mas também permitiu + na frente. Isso irá removê-lo.

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

Aqui está uma derivada que também irá bloquear o ponto decimal para ser inserido duas vezes

HTML

   

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

Estendendo Adam Thomas resposta você pode facilmente tornar esta diretiva mais genérica, adicionando o argumento de input com regexp personalizado:

 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

   

Live on CodePen

Por favor, confira o meu componente que irá ajudá-lo a permitir apenas um determinado tipo de dados. Atualmente suportando inteiro, decimal, string e hora (HH: MM).

  • string – String é permitida com comprimento máximo opcional
  • integer – Inteiro permitido apenas com valor máximo opcional
  • decimal – Decimal permitido apenas com pontos decimais opcionais e valor máximo (por padrão, 2 pontos decimais)
  • time – 24 h Formato de hora (HH: MM) permitido somente

https://github.com/ksnimmy/txDataType

Espero que ajude.

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

DÍGITOS

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

directivas angulares para validar números