Chciałbym oprzeć się na odpowiedzi udzielonej przez @omeralper, która moim zdaniem była dobrą podstawą do solidnego rozwiązania.
Proponuję uproszczoną i aktualną wersję z najnowszymi standardami sieciowymi. Należy zauważyć, że kod event.keycode został usunięty ze standardów sieciowych, a przyszłe aktualizacje przeglądarki mogą go już nie obsługiwać. Zobacz https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
Ponadto metoda
String.fromCharCode(e.keyCode);
nie gwarantuje, że keyCode odnoszący się do klawisza wciskanego przez użytkownika jest odwzorowywany na oczekiwaną literę identyfikowaną na klawiaturze użytkownika, ponieważ różne konfiguracje klawiatury spowodują, że dany kod klawisza będzie miał różne znaki. Użycie tego spowoduje wprowadzenie błędów, które są trudne do zidentyfikowania i mogą łatwo uszkodzić funkcjonalność niektórych użytkowników. Raczej proponuję użycie event.key, zobacz dokumentację tutaj https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
Ponadto chcemy, aby wynikowe dane wyjściowe były poprawnymi liczbami dziesiętnymi. Oznacza to, że należy zaakceptować liczby 1, 11.2, 5000.2341234, ale nie należy przyjąć wartości 1.1.2.
Zauważ, że w moim rozwiązaniu wykluczam funkcję wycinania, kopiowania i wklejania, ponieważ otwiera okna w poszukiwaniu błędów, zwłaszcza gdy ludzie wklejają niechciany tekst w powiązanych polach. To wymagałoby procesu czyszczenia w programie obsługi klucza; co nie jest przedmiotem tego wątku.
Oto rozwiązanie, które proponuję.
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();
}
}
}