I have this piece of code
<input matInput type="number" [(ngModel)]="value"
(ngModelChange)="onChange(true)" />
But I want to be able to enter only numbers, not other characters like + , . -
I found this directive https://stackblitz.com/edit/angular-numbers-only-directive?file=app%2Fapp.component.ts
The problem is that the onChange method is called even if I enter an invalid value. I don't want to put the same condition in the onChange method; I want to be able to modify the directive to emit the event or not. So it should only work if it's actually a number.
I found some solutions with keyPress, but it is deprecated.
I am using angular 19
I found a solution that seems to work. It handles both the cursor and the event emit.
<input matInput numbersOnly [(ngModel)]="value"
(ngModelChange)="onChange(true)" />
Directive
import {Directive, HostListener} from "@angular/core";
@Directive({
selector: '[numbersOnly]',
})
export class NumbersOnlyDirective {
private readonly regExpr = new RegExp('^([1-9]\\d*|0)$');
constructor() {
}
@HostListener('beforeinput', ['$event'])
onBeforeInput(event: InputEvent) {
if (!event.data) {
return;
}
const input = event.target as HTMLInputElement;
const currentVal = input.value;
const start = input.selectionStart || 0;
const end = input.selectionEnd || 0;
const nextVal =
currentVal.substring(0, start) + event.data + currentVal.substring(end);
if (!this.regExpr.test(nextVal)) {
event.preventDefault();
}
}
}