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 {
private regex: RegExp = new RegExp(/^[0-9]+(\.[0-9]*){0,1}$/g);
private specialKeys: Array<string> = [ 'Backspace', 'Tab', 'End', 'Home' ];
constructor(private el: ElementRef) {
}
@HostListener('keydown', [ '$event' ])
onKeyDown(event: KeyboardEvent) {
if (this.specialKeys.indexOf(event.key) !== -1) {
return;
}
let current: string = this.el.nativeElement.value;
let next: string = current.concat(event.key);
if (next && !String(next).match(this.regex)) {
event.preventDefault();
}
}
}