Vorrei basarmi sulla risposta data da @omeralper, che a mio parere ha fornito una buona base per una solida soluzione.
Quello che sto proponendo è una versione semplificata e aggiornata con i più recenti standard web. È importante notare che event.keycode viene rimosso dagli standard web e che i futuri aggiornamenti del browser potrebbero non supportarlo più. Vedi https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
Inoltre, il metodo
String.fromCharCode(e.keyCode);
non garantisce che il keyCode relativo al tasto premuto dall'utente corrisponda alla lettera prevista come identificata sulla tastiera dell'utente, poiché diverse configurazioni di tastiera risulteranno in un particolare keycode caratteri diversi. L'utilizzo di questo introdurrà bug che sono difficili da identificare e possono facilmente interrompere la funzionalità per alcuni utenti. Piuttosto sto proponendo l'uso di event.key, vedere la documentazione qui https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
Inoltre, vogliamo solo che l'output risultante sia un decimale valido. Ciò significa che i numeri 1, 11.2, 5000.2341234 dovrebbero essere accettati, ma il valore 1.1.2 non dovrebbe essere accettato.
Nota che nella mia soluzione sto escludendo la funzionalità taglia, copia e incolla poiché apre finestre per bug, specialmente quando le persone incollano testo indesiderato nei campi associati. Ciò richiederebbe un processo di pulizia su un gestore di keyup; che non è lo scopo di questo thread.
Ecco la soluzione che sto proponendo.
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();
}
}
}