No Angular 2, como posso mascarar um campo de entrada (caixa de texto) de forma que ele aceite apenas números e não caracteres alfabéticos?
Eu tenho a seguinte entrada de HTML:
<input
type="text"
*ngSwitchDefault
class="form-control"
(change)="onInputChange()"
[(ngModel)]="config.Value"
(focus)="handleFocus($event)"
(blur)="handleBlur($event)"
/>
A entrada acima é uma entrada de texto genérica que pode ser usada como um campo de texto simples ou como um campo numérico, por exemplo, para mostrar o ano.
Usando o Angular 2, como posso usar o mesmo controle de entrada e aplicar algum tipo de filtro / máscara neste campo, de forma que aceite apenas números?
Quais são as diferentes maneiras de fazer isso?
Observação: preciso fazer isso usando apenas a caixa de texto e não o tipo de número de entrada.
html
angular
input
angularjs-directive
Aniruddha Pondhe
fonte
fonte
Respostas:
Você pode usar as diretivas angular2. Plunkr
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[OnlyNumber]' }) export class OnlyNumber { constructor(private el: ElementRef) { } @Input() OnlyNumber: boolean; @HostListener('keydown', ['$event']) onKeyDown(event) { let e = <KeyboardEvent> event; if (this.OnlyNumber) { if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 || // Allow: Ctrl+A (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+C (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+V (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+X (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) || // Allow: home, end, left, right (e.keyCode >= 35 && e.keyCode <= 39)) { // let it happen, don't do anything return; } // Ensure that it is a number and stop the keypress if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) { e.preventDefault(); } } } }
e você precisa escrever o nome da diretiva em sua entrada como um atributo
<input OnlyNumber="true" />
não se esqueça de escrever sua diretiva no array de declarações de seu módulo.
Usando regex, você ainda precisa de chaves funcionais
export class OnlyNumber { regexStr = '^[0-9]*$'; constructor(private el: ElementRef) { } @Input() OnlyNumber: boolean; @HostListener('keydown', ['$event']) onKeyDown(event) { let e = <KeyboardEvent> event; if (this.OnlyNumber) { if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 || // Allow: Ctrl+A (e.keyCode == 65 && e.ctrlKey === true) || // Allow: Ctrl+C (e.keyCode == 67 && e.ctrlKey === true) || // Allow: Ctrl+V (e.keyCode == 86 && e.ctrlKey === true) || // Allow: Ctrl+X (e.keyCode == 88 && e.ctrlKey === true) || // Allow: home, end, left, right (e.keyCode >= 35 && e.keyCode <= 39)) { // let it happen, don't do anything return; } let ch = String.fromCharCode(e.keyCode); let regEx = new RegExp(this.regexStr); if(regEx.test(ch)) return; else e.preventDefault(); } } }
fonte
(e.keyCode == 86 && e.ctrlKey === true)
às condições, copiar está funcionando, mas colar não funcionoue.keyCode == 109 || e.keyCode ==190
para.
e-
mas-
não é aceito?Se você não quer uma diretiva
https://stackblitz.com/edit/numeric-only
em component.html
<input (keypress)="numberOnly($event)" type="text">
em component.ts
export class AppComponent { numberOnly(event): boolean { const charCode = (event.which) ? event.which : event.keyCode; if (charCode > 31 && (charCode < 48 || charCode > 57)) { return false; } return true; } }
fonte
Eu sei que esta é uma questão antiga, mas como esta é uma funcionalidade comum, quero compartilhar as modificações que fiz:
Substitua strings como ".33" e "33." para as versões corretas: 0,33 e 33,0
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[NumbersOnly]' }) export class NumbersOnly { @Input() allowDecimals: boolean = true; @Input() allowSign: boolean = false; @Input() decimalSeparator: string = '.'; previousValue: string = ''; // -------------------------------------- // Regular expressions integerUnsigned: string = '^[0-9]*$'; integerSigned: string = '^-?[0-9]+$'; decimalUnsigned: string = '^[0-9]+(.[0-9]+)?$'; decimalSigned: string = '^-?[0-9]+(.[0-9]+)?$'; /** * Class constructor * @param hostElement */ constructor(private hostElement: ElementRef) { } /** * Event handler for host's change event * @param e */ @HostListener('change', ['$event']) onChange(e) { this.validateValue(this.hostElement.nativeElement.value); } /** * Event handler for host's paste event * @param e */ @HostListener('paste', ['$event']) onPaste(e) { // get and validate data from clipboard let value = e.clipboardData.getData('text/plain'); this.validateValue(value); e.preventDefault(); } /** * Event handler for host's keydown event * @param event */ @HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) { let cursorPosition: number = e.target['selectionStart']; let originalValue: string = e.target['value']; let key: string = this.getName(e); let controlOrCommand = (e.ctrlKey === true || e.metaKey === true); let signExists = originalValue.includes('-'); let separatorExists = originalValue.includes(this.decimalSeparator); // allowed keys apart from numeric characters let allowedKeys = [ 'Backspace', 'ArrowLeft', 'ArrowRight', 'Escape', 'Tab' ]; // when decimals are allowed, add // decimal separator to allowed codes when // its position is not close to the the sign (-. and .-) let separatorIsCloseToSign = (signExists && cursorPosition <= 1); if (this.allowDecimals && !separatorIsCloseToSign && !separatorExists) { if (this.decimalSeparator == '.') allowedKeys.push('.'); else allowedKeys.push(','); } // when minus sign is allowed, add its // key to allowed key only when the // cursor is in the first position, and // first character is different from // decimal separator let firstCharacterIsSeparator = (originalValue.charAt(0) != this.decimalSeparator); if (this.allowSign && !signExists && firstCharacterIsSeparator && cursorPosition == 0) { allowedKeys.push('-'); } // allow some non-numeric characters if (allowedKeys.indexOf(key) != -1 || // Allow: Ctrl+A and Command+A (key == 'a' && controlOrCommand) || // Allow: Ctrl+C and Command+C (key == 'c' && controlOrCommand) || // Allow: Ctrl+V and Command+V (key == 'v' && controlOrCommand) || // Allow: Ctrl+X and Command+X (key == 'x' && controlOrCommand)) { // let it happen, don't do anything return; } // save value before keydown event this.previousValue = originalValue; // allow number characters only let isNumber = (new RegExp(this.integerUnsigned)).test(key); if (isNumber) return; else e.preventDefault(); } /** * Test whether value is a valid number or not * @param value */ validateValue(value: string): void { // choose the appropiate regular expression let regex: string; if (!this.allowDecimals && !this.allowSign) regex = this.integerUnsigned; if (!this.allowDecimals && this.allowSign) regex = this.integerSigned; if (this.allowDecimals && !this.allowSign) regex = this.decimalUnsigned; if (this.allowDecimals && this.allowSign) regex = this.decimalSigned; // when a numbers begins with a decimal separator, // fix it adding a zero in the beginning let firstCharacter = value.charAt(0); if (firstCharacter == this.decimalSeparator) value = 0 + value; // when a numbers ends with a decimal separator, // fix it adding a zero in the end let lastCharacter = value.charAt(value.length-1); if (lastCharacter == this.decimalSeparator) value = value + 0; // test number with regular expression, when // number is invalid, replace it with a zero let valid: boolean = (new RegExp(regex)).test(value); this.hostElement.nativeElement['value'] = valid ? value : 0; } /** * Get key's name * @param e */ getName(e): string { if (e.key) { return e.key; } else { // for old browsers if (e.keyCode && String.fromCharCode) { switch (e.keyCode) { case 8: return 'Backspace'; case 9: return 'Tab'; case 27: return 'Escape'; case 37: return 'ArrowLeft'; case 39: return 'ArrowRight'; case 188: return ','; case 190: return '.'; case 109: return '-'; // minus in numbpad case 173: return '-'; // minus in alphabet keyboard in firefox case 189: return '-'; // minus in alphabet keyboard in chrome default: return String.fromCharCode(e.keyCode); } } } }
Uso:
<input NumbersOnly [allowDecimals]="true" [allowSign]="true" type="text">
fonte
Gostaria de desenvolver a resposta dada por @omeralper, que, em minha opinião, forneceu uma boa base para uma solução sólida.
O que estou propondo é uma versão simplificada e atualizada com os padrões da web mais recentes. É importante observar que event.keycode foi removido dos padrões da web e as atualizações futuras do navegador podem não suportá-lo mais. Consulte https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
Além disso, o método
String.fromCharCode(e.keyCode);
não garante que o keyCode pertencente à tecla que está sendo pressionada pelo usuário mapeie para a letra esperada conforme identificada no teclado do usuário, uma vez que diferentes configurações de teclado resultarão em um determinado código de tecla em caracteres diferentes. Usar isso irá introduzir bugs que são difíceis de identificar e podem facilmente quebrar a funcionalidade para certos usuários. Em vez disso, estou propondo o uso de event.key, consulte os documentos aqui https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
Além disso, queremos apenas que a saída resultante seja um decimal válido. Isso significa que os números 1, 11.2, 5000.2341234 devem ser aceitos, mas o valor 1.1.2 não deve ser aceito.
Observe que, na minha solução, estou excluindo a funcionalidade de recortar, copiar e colar, uma vez que abre janelas para erros, especialmente quando as pessoas colam texto indesejado em campos associados. Isso exigiria um processo de limpeza em um manipulador de teclas; que não é o escopo deste tópico.
Aqui está a solução que estou propondo.
import { Directive, ElementRef, HostListener } from '@angular/core'; @Directive({ selector: '[myNumberOnly]' }) export class NumberOnlyDirective { // Allow decimal numbers. The \. is only allowed once to occur private regex: RegExp = new RegExp(/^[0-9]+(\.[0-9]*){0,1}$/g); // Allow key codes for special events. Reflect : // Backspace, tab, end, home private specialKeys: Array<string> = [ 'Backspace', 'Tab', 'End', 'Home' ]; constructor(private el: ElementRef) { } @HostListener('keydown', [ '$event' ]) onKeyDown(event: KeyboardEvent) { // Allow Backspace, tab, end, and home keys if (this.specialKeys.indexOf(event.key) !== -1) { return; } // Do not use event.keycode this is deprecated. // See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode let current: string = this.el.nativeElement.value; // We need this because the current value on the DOM element // is not yet updated with the value from this event let next: string = current.concat(event.key); if (next && !String(next).match(this.regex)) { event.preventDefault(); } } }
fonte
Uma solução mais concisa. Experimente esta diretiva.
Também pode ser usado se você estiver usando ReactiveForms.
export class NumberOnlyDirective { private el: NgControl; constructor(private ngControl: NgControl) { this.el = ngControl; } // Listen for the input event to also handle copy and paste. @HostListener('input', ['$event.target.value']) onInput(value: string) { // Use NgControl patchValue to prevent the issue on validation this.el.control.patchValue(value.replace(/[^0-9]/g, '')); } }
Use-o em suas entradas como este:
<input matInput formControlName="aNumberField" numberOnly>
fonte
<input type="text" (keypress)="keyPress($event)"> keyPress(event: any) { const pattern = /[0-9\+\-\ ]/; let inputChar = String.fromCharCode(event.charCode); if (event.keyCode != 8 && !pattern.test(inputChar)) { event.preventDefault(); } }
fonte
Você precisa usar type = "número" em vez de texto. Você também pode especificar os números máximo e mínimo
<input type="number" name="quantity" min="1" max="5">
fonte
type="number"
é que ele aceita caracterese
como parte da notação científicavocê pode conseguir assim
<input type="text" pInputText (keypress)="onlyNumberKey($event)" maxlength="3"> onlyNumberKey(event) { return (event.charCode == 8 || event.charCode == 0) ? null : event.charCode >= 48 && event.charCode <= 57; } //for Decimal you can use this as onlyDecimalNumberKey(event) { let charCode = (event.which) ? event.which : event.keyCode; if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57)) return false; return true; }
espero que isso ajude você.
fonte
Você pode usar regex:
<input type="text" (keypress)="numericOnly($event)"> numericOnly(event): boolean { let patt = /^([0-9])$/; let result = patt.test(event.key); return result; }
fonte
Use o
pattern
atributo para entrada como abaixo:<input type="text" pattern="[0-9]+" >
fonte
Eu sei que isso tem muitas respostas, mas eu precisava lidar com o seguinte (que nenhuma das respostas parecia apoiar totalmente):
A solução me permite definir uma área de texto como esta:
<textarea class="form-control" [(ngModel)]="this.myModelVariable" appOnlyNumbers [allowNegative]="true" [allowMultiLine]="true" [allowDecimal]="true" [maxLength]="10" placeholder="Enter values (one per line)"></textarea>
Ou se eu só quero números inteiros positivos
<textarea class="form-control" [(ngModel)]="this.myModelVariable" appOnlyNumbers [allowMultiLine]="true" [maxLength]="9" placeholder="Enter values (one per line)"></textarea>
Aqui está minha diretriz:
import { Directive, HostListener, Input, ElementRef } from '@angular/core'; @Directive({ selector: '[appOnlyNumbers]' }) export class OnlyNumbersDirective { constructor(private el: ElementRef) { } @Input() allowMultiLine: boolean = false; @Input() allowNegative: boolean = false; @Input() allowDecimal: boolean = false; @Input() maxLength: number = 0; regex: RegExp; @HostListener('keypress', ['$event']) onKeyPress(event: KeyboardEvent) { this.validate(event, event.key === 'Enter' ? '\n' : event.key); } @HostListener('paste', ['$event']) onPaste(event: Event) { const pastedText = (<any>window).clipboardData && (<any>window).clipboardData.getData('Text') // If IE, use window || <ClipboardEvent>event && (<ClipboardEvent>event).clipboardData.getData('text/plain'); // Non-IE browsers this.validate(event, pastedText); } @HostListener('cut', ['$event']) onCut(event: Event) { this.validate(event, ''); } validate(event: Event, text: string) { const txtInput = this.el.nativeElement; const newValue = (txtInput.value.substring(0, txtInput.selectionStart) + text + txtInput.value.substring(txtInput.selectionEnd)); if (!this.regex) { this.regex = <RegExp>eval('/^' + (this.allowNegative ? '-?' : '') + (this.allowDecimal ? '((\\d+\\.?)|(\\.?))\\d*' : '\\d*') + '$/g'); } var lines = this.allowMultiLine ? newValue.split('\n') : [newValue]; for (let line of lines) { let lineText = line.replace('\r', ''); if (this.maxLength && lineText.length > this.maxLength || !lineText.match(this.regex)) { event.preventDefault(); return; } } } }
fonte
Para fazer isso, vinculei uma função ao método onInput como este:
(input)="stripText(infoForm.get('uin'))
Aqui está o exemplo dentro do meu formulário:
<form [formGroup]="infoForm" (submit)="next()" class="ui form"> <input type="text" formControlName="uin" name="uin" id="uin" (input)="stripText(infoForm.get('uin'))" required/> </form>
Em seguida, adicionei a seguinte função ao meu componente:
stripText(control: FormControl) { control.setValue(control.value.replace(/[^0-9]/g, '')); }
Este regex
/[^0-9]/g
procura por qualquer coisa que não seja um número e usando.replace
eu o defini para ser substituído por nada. Portanto, quando um usuário tenta digitar um caractere que não é um número (neste caso, um caractere que não é de zero a nove), parece que nada acontece na caixa de texto.fonte
Bem, obrigado a JeanPaul A. e rdanielmurphy. Eu fiz minha própria diretiva personalizada para limitar o campo de entrada a apenas um número. Também foram adicionados os atributos de entrada máximo e mínimo. Funcionará no angular 7 também.
Angular
import { Directive, ElementRef, Input, HostListener } from '@angular/core'; @Directive({ selector: '[appNumberOnly]' }) export class NumberOnlyDirective { // Allow decimal numbers. The \. is only allowed once to occur private regex: RegExp = new RegExp(/^[0-9]+(\.[0-9]*){0,1}$/g); // Allow key codes for special events. Reflect : // Backspace, tab, end, home private specialKeys: Array<string> = ['Backspace', 'Tab', 'End', 'Home']; constructor(private el: ElementRef) { } @Input() maxlength: number; @Input() min: number; @Input() max: number; @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent) { // Allow Backspace, tab, end, and home keys if (this.specialKeys.indexOf(event.key) !== -1) { return; } // Do not use event.keycode this is deprecated. // See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode const current: string = this.el.nativeElement.value; // We need this because the current value on the DOM element // is not yet updated with the value from this event const next: string = current.concat(event.key); if (next && !String(next).match(this.regex) || (this.maxlength && next.length > this.maxlength) || (this.min && +next < this.min) || (this.max && +next >= this.max)) { event.preventDefault(); } } @HostListener('paste', ['$event']) onPaste(event) { // Don't allow pasted text that contains non-numerics const pastedText = (event.originalEvent || event).clipboardData.getData('text/plain'); if (pastedText) { const regEx = new RegExp('^[0-9]*$'); if (!regEx.test(pastedText) || (this.maxlength && pastedText.length > this.maxlength) || (this.min && +pastedText < this.min) || (this.max && +pastedText >= this.max)) { event.preventDefault(); } } } }
HTML
<input type="text" class="text-area" [(ngModel)]="itemName" maxlength="3" appNumberOnly />
fonte
Uma abordagem moderna para a melhor resposta (sem e.keyCode obsoleto):
@HostListener('keydown', ['$event']) onKeyDown(event) { let e = <KeyboardEvent> event; if (['Delete', 'Backspace', 'Tab', 'Escape', 'Enter', 'NumLock', 'ArrowLeft', 'ArrowRight', 'End', 'Home', '.'].indexOf(e.key) !== -1 || // Allow: Ctrl+A (e.key === 'a' && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+C (e.key === 'c' && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+V (e.key === 'v' && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+X (e.key === 'x' && (e.ctrlKey || e.metaKey))) { // let it happen, don't do anything return; } // Ensure that it is a number and stop the keypress if ((e.shiftKey || ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].indexOf(e.key) === -1)) { e.preventDefault(); } }
fonte
Diretiva Arbitrary RegExp
Aqui está uma pequena diretiva que usa regexp arbitrária e bloqueia o usuário para digitar um valor inválido
Exibir trecho de código
import {Directive, HostListener, Input} from '@angular/core'; @Directive({selector: '[allowedRegExp]'}) export class AllowedRegExpDirective { @Input() allowedRegExp: string; @HostListener('keydown', ['$event']) onKeyDown(event: any) { // case: selected text (by mouse) - replace it let s= event.target.selectionStart; let e= event.target.selectionEnd; let k= event.target.value + event.key; if(s!=e) { k= event.target.value k= k.slice(0,s) + event.key + k.slice(e,k.length); } // case: special characters (ignore) if(['ArrowLeft','ArrowRight','ArrowUp','ArroDown','Backspace','Tab','Alt' 'Shift','Control','Enter','Delete','Meta'].includes(event.key)) return; // case: normal situation - chceck regexp let re = new RegExp(this.allowedRegExp); if(!re.test(k)) event.preventDefault(); } }
Para mascarar apenas números, use
<input [allowedRegExp]="'^[0-9]*$'" type="text" ... >
fonte
Basta criar uma diretiva e adicionar hostlistener abaixo:
@HostListener('input', ['$event']) onInput(event: Event) { this.elementRef.nativeElement.value = (<HTMLInputElement>event.currentTarget).value.replace(/[^0-9]/g, ''); }
Substitua o texto inválido por vazio. Todas as teclas e combinações de teclas agora funcionarão em todos os navegadores até o IE9.
fonte
Padrão para o padrão de número de celular válido ('^ ((\ + 91 -?) | 0)? [0-9] {10} $')
Padrão para aceitar apenas o número do padrão da caixa de texto ('[0-9] *')
padrão para aceitar apenas o número com um número específico, por exemplo: Pincode. padrão ('^ [0-9] {5} $')
fonte
Fiz algumas modificações na diretiva acima e implementei min, max, maxlength.
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[numberOnly]' }) export class NumbersOnlyDirective { private regex: RegExp = new RegExp(/[0-9]/g); // Allow key codes for special events. Reflect : private specialKeys: Array<number> = [46, 8, 9, 27, 13, 110, 190, 35, 36, 37, 39]; // Backspace, tab, end, home @Input() maxlength: number; @Input() min: number; @Input() max: number; constructor(private el: ElementRef) { } @HostListener('keydown', ['$event']) onKeyDown(event: KeyboardEvent) { e = <KeyboardEvent>event; if (( (this.specialKeys.indexOf(event.which) > -1) || // to allow backspace, enter, escape, arrows (e.which == 65 && e.ctrlKey == true) || // Allow: Ctrl+C (e.which == 67 && e.ctrlKey == true) || // Allow: Ctrl+X (e.which == 88 && e.ctrlKey == true))) { return; } else if (// to allow numbers (e.which >= 48 && e.which <= 57) || // to allow numpad number (event.which >= 96 && event.which <= 105)) { } else { event.preventDefault(); } let current: string = this.el.nativeElement.value; let next: string = current.concat(event.key); if ((next && !String(next).match(this.regex)) || (this.maxlength && next.length > this.maxlength) || (this.min && +next < this.min) || (this.max && +next >= this.max)) { event.preventDefault(); } } }
fonte
da resposta de @omeralper. Mudo um pouco que não aceita ponto ascii (código 110,190). e use let ch = (e.key); para comparar com a expressão regular quando você altera o idioma (como o tailandês ou japonês), ele não aceitará o caractere desse idioma
export class OnlyNumber { regexStr = '^[0-9]*$'; constructor(private el: ElementRef) { } @Input() OnlyNumber: boolean; @HostListener('keydown', ['$event']) onKeyDown(event) { let e = <KeyboardEvent> event; if (this.OnlyNumber) { // console.log(event, this.OnlyNumber); if ([46, 8, 9, 27, 13].indexOf(e.keyCode) !== -1) { return; } let ch = (e.key); let regEx = new RegExp(this.regexStr); if(regEx.test(ch)) return; else e.preventDefault(); } } }
espero que ajude :)
fonte
Você pode criar este Validador e importá-lo em seu componente.
Valida basicamente a string de entrada do formulário:
Para implementá-lo em seu projeto:
importar em seu componente
import { NumberValidator } from '../../validators/number.validator';
inputNumber: ['', [NumberValidator.isInteger]],
(change)="deleteCharIfInvalid()"
a à entrada, seform.get('inputNumber').hasError('isInteger')
fortrue
, delete o último char inserido.// FILE: src/app/validators/number.validator.ts import { FormControl } from '@angular/forms'; export interface ValidationResult { [key: string]: boolean; } export class NumberValidator { public static isInteger(control: FormControl): ValidationResult { // check if string has a dot let hasDot:boolean = control.value.indexOf('.') >= 0 ? true : false; // convert string to number let number:number = Math.floor(control.value); // get result of isInteger() let integer:boolean = Number.isInteger(number); // validate conditions let valid:boolean = !hasDot && integer && number>0; console.log('isInteger > valid', hasDot, number, valid); if (!valid) { return { isInteger: true }; } return null; } }
fonte
Number.isInteger(Math.floor(control.value))
será sempre verdade? Eu acho que deveria ser emparseFloat
vez disso.Com suporte para higienização de conteúdo colado:
import { Directive, ElementRef, HostListener, Input } from '@angular/core'; @Directive({ selector: '[NumbersOnly]' }) export class NumbersOnlyDirective { DIGITS_REGEXP = new RegExp(/\D/g); constructor(private el: ElementRef) { // Sanatize clipboard by removing any non-numeric input after pasting this.el.nativeElement.onpaste = (e:any) => { e.preventDefault(); let text; let clp = (e.originalEvent || e).clipboardData; if (clp === undefined || clp === null) { text = (<any>window).clipboardData.getData('text') || ''; if (text !== '') { text = text.replace(this.DIGITS_REGEXP, ''); if (window.getSelection) { let newNode = document.createElement('span'); newNode.innerHTML = text; window.getSelection().getRangeAt(0).insertNode(newNode); } else { (<any>window).selection.createRange().pasteHTML(text); } } } else { text = clp.getData('text/plain') || ''; if (text !== '') { text = text.replace(this.DIGITS_REGEXP, ''); document.execCommand('insertText', false, text); } } }; } @HostListener('keydown', ['$event']) onKeyDown(event) { let e = <KeyboardEvent> event; if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 || // Allow: Ctrl+A (e.keyCode === 65 && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+C (e.keyCode === 67 && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+V (e.keyCode === 86 && (e.ctrlKey || e.metaKey)) || // Allow: Ctrl+X (e.keyCode === 88 && (e.ctrlKey || e.metaKey)) || // Allow: home, end, left, right (e.keyCode >= 35 && e.keyCode <= 39)) { // let it happen, don't do anything return; } // Ensure that it is a number and stop the keypress if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) { e.preventDefault(); } } }
fonte
Aqui é fácil: Diretriz simples No evento keydown, ela verifica se o comprimento de uma chave é um e a chave não é um número para
preventDefault()
e não renderiza aquele caractere.import {Directive, ElementRef, HostListener} from '@angular/core'; @Directive({ selector: '[numbersOnly]' }) export class NumbersOnlyDirective { @HostListener('keydown', ['$event']) keyDownEvent(event: KeyboardEvent) { if (event.key.length === 1 && (event.which < 48 || event.which > 57)) { event.preventDefault(); } } }
HTML:
<input type="text" [(ngModel)]="numModel" numbersOnly />
Limitações: Permitirá colar com o mouse dessa forma aceitará outros caracteres. Para evitar isso, você pode passar o modelo como entrada para a diretiva e
ngOnChage
para esse modelo alterar o valor apenas para números:Como abaixo:
EDIT: Adicionado código para detectar mudança no modelo e atualizar o valor da entrada
import {Directive, ElementRef, HostListener, Input, OnChanges} from '@angular/core'; @Directive({ selector: '[numbersOnly]' }) export class NumbersOnlyDirective implements OnChanges { @Input() numbersOnly: any; constructor(private el: ElementRef) {} @HostListener('keydown', ['$event']) keyDownEvent(event: KeyboardEvent) { // Add other conditions if need to allow ctr+c || ctr+v if (event.key.length === 1 && (event.which < 48 || event.which > 57)) { event.preventDefault(); } } ngOnChanges(changes) { if (changes.numbersOnly) { this.el.nativeElement.value = this.el.nativeElement.value.replace(/[^0-9]/g, ''); } } }
HTML:
<input type="text" [(ngModel)]="numModel" [numbersOnly]="numModel" />
fonte
import {Directive, ElementRef, HostListener, Output, EventEmitter} from '@angular/core'; //only-digits @Directive({ selector: '[only-digits]' }) export class OnlyDigits { constructor(public el: ElementRef) { this.el.nativeElement.onkeypress = (evt) => { if (evt.which < 48 || evt.which > 57) { evt.preventDefault(); } }; } }
A diretiva também é a melhor maneira de fazer isso
fonte
<input oninput="this.value=this.value.replace(/[^0-9]/g,'')"
ou: 2. no arquivo HTML:
<input [(ngModel)]="data" (keypress)="stripText($event)" class="form-control">
no arquivo ts:
stripText(event) { const seperator = '^([0-9])'; const maskSeperator = new RegExp(seperator , 'g'); let result =maskSeperator.test(event.key); return result; }
Esta 2 solução funciona
fonte
fromCharCode retorna 'a' ao pressionar o teclado numérico '1', então este metóide deve ser evitado
(admin: não poderia comentar como de costume)
fonte
Eu vi muitos comentários sobre como copiar / colar.
Para pegar carona na resposta @omeralper, você pode adicionar um manipulador de eventos paste à diretiva onlyNumber para lidar com copiar / colar:
@HostListener('paste', ['$event']) onPaste(event) { // Don't allow pasted text that contains non-numerics var pastedText = (event.originalEvent || event).clipboardData.getData('text/plain'); if (pastedText) { var regEx = new RegExp('^[0-9]*$'); if (!regEx.test(pastedText)) { event.preventDefault(); } }
Isso só permitirá que o conteúdo seja copiado e colado na caixa de texto SOMENTE se for um número. Essa é a solução mais simples. Alterar o conteúdo da área de transferência para remover números não numéricos é muito mais complicado e pode não valer a pena.
Para obter texto colado do IE, você pode usar o seguinte:
window.clipboardData.getData('Text');
fonte
Se você usar primeng e Angular 6 ou superior, existe o componente p-inputMask. Impede a digitação alfa E valores negativos https://www.primefaces.org/primeng/#/inputmask
fonte
Não seria simples o suficiente apenas escrever
onlyNumbers(event) { if(isNaN(event.target.value * 1)) { console.log("Not a number") } else { console.log("Number") }
}
fonte
Você também pode criar uma diretiva que implemente a interface ControlValueAccessor ( https://angular.io/api/forms/ControlValueAccessor ).
Veja o exemplo de trabalho aqui: https://stackblitz.com/edit/angular-input-field-to-accept-only-numbers
Você pode ouvir o evento de 'entrada' e não há necessidade de verificar os códigos de tecla. Ele suporta copiar e colar e se integra perfeitamente com a API Angular Forms devido à Interface ControlValueAccessor.
Diretriz:
@Directive({ ... selector: '[onlyNumber]' }) export class OnlyNumberDirective implements ControlValueAccessor { private onChange: (val: string) => void; ... private value: string; constructor( private elementRef: ElementRef, private renderer: Renderer2 ) { } ... @HostListener('input', ['$event.target.value']) onInputChange(value: string) { const filteredValue: string = filterValue(value); this.updateTextInput(filteredValue, this.value !== filteredValue); } private updateTextInput(value, propagateChange) { this.renderer.setProperty(this.elementRef.nativeElement, 'value', value); if (propagateChange) { this.onChange(value); } this.value = value; } // ControlValueAccessor Interface ... registerOnChange(fn: any): void { this.onChange = fn; } writeValue(value: string): void { value = value ? String(value) : ''; this.updateTextInput(value, false); } } function filterValue(value): string { return value.replace(/[^0-9]*/g, ''); }
Uso:
<input name="number" type="text" onlyNumber [(ngModel)]="someNumber">
fonte
Fundição porque funciona também com 0 líder, como 00345
@Directive({ selector: '[appOnlyDigits]' }) export class AppOnlyDigitsDirective { @HostListener('input', ['$event']) onKeyDown(ev: KeyboardEvent) { const input = ev.target as HTMLInputElement; input.value = String(input.value.replace(/\D+/g, '')); } }
fonte