Tôi muốn xây dựng câu trả lời do @omeralper đưa ra, theo quan điểm của tôi, câu trả lời này đã cung cấp nền tảng tốt cho một giải pháp vững chắc.
Những gì tôi đang đề xuất là một phiên bản đơn giản hóa và cập nhật với các tiêu chuẩn web mới nhất. Điều quan trọng cần lưu ý là event.keycode bị xóa khỏi các tiêu chuẩn web và các bản cập nhật trình duyệt trong tương lai có thể không hỗ trợ nó nữa. Xem https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
Hơn nữa, phương pháp
String.fromCharCode(e.keyCode);
không đảm bảo rằng Mã khóa liên quan đến phím được người dùng nhấn ánh xạ tới ký tự mong đợi như được xác định trên bàn phím của người dùng, vì các cấu hình bàn phím khác nhau sẽ dẫn đến một mã khóa cụ thể các ký tự khác nhau. Sử dụng điều này sẽ tạo ra các lỗi khó xác định và có thể dễ dàng phá vỡ chức năng cho một số người dùng nhất định. Thay vì tôi đang đề xuất sử dụng event.key, hãy xem tài liệu tại đây https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
Hơn nữa, chúng tôi chỉ muốn kết quả đầu ra là một số thập phân hợp lệ. Điều này có nghĩa là các số 1, 11.2, 5000.2341234 nên được chấp nhận, nhưng không nên chấp nhận giá trị 1.1.2.
Lưu ý rằng trong giải pháp của tôi, tôi không loại trừ chức năng cắt, sao chép và dán vì nó mở cửa sổ cho các lỗi, đặc biệt là khi mọi người dán văn bản không mong muốn vào các trường được liên kết. Điều đó sẽ yêu cầu một quá trình dọn dẹp trên trình xử lý keyup; mà không phải là phạm vi của chủ đề này.
Đây là giải pháp tôi đang đề xuất.
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();
}
}
}