v1 Online Demo: https://codesandbox.io/s/v1-angular-numeric-ljwlb
v2 Online Demo: https://codesandbox.io/s/v2-angular-numeric-3w2wr
<input numeric type="text">
<input numeric decimals="2" type="text">
// Version 2
import {
Directive,
ElementRef,
HostListener,
Input
} from "@angular/core";
@Directive({
selector: "[numeric]"
})
export class NumericDirective {
@Input("decimals") decimals: int = 0;
private check(value: string) {
if (this.decimals <= 0) {
return String(value).match(new RegExp(/^\d+$/));
} else {
var regExpString =
"^\\s*((\\d+(\\.\\d{0," +
this.decimals +
"})?)|((\\d*(\\.\\d{1," +
this.decimals +
"}))))\\s*$";
return String(value).match(new RegExp(regExpString));
}
}
private run(oldValue) {
setTimeout(() => {
let currentValue: string = this.el.nativeElement.value;
if (currentValue !== '' && !this.check(currentValue)) {
this.el.nativeElement.value = oldValue;
}
});
}
constructor(private el: ElementRef) {}
@HostListener("keydown", ["$event"])
onKeyDown(event: KeyboardEvent) {
this.run(this.el.nativeElement.value);
}
@HostListener("paste", ["$event"])
onPaste(event: ClipboardEvent) {
this.run(this.el.nativeElement.value);
}
}
Thanks.
I also added the following changes so I can edit the number at any place in the input:
let current: string = this.el.nativeElement.value;
let position: number = this.el.nativeElement.selectionStart;
let next: string = [current.slice(0, position), event.key, current.slice(position)].join('');
I would also suggest to check condition on Backspace and Delete.