I'm not satisfied with the default behavior of the html number input, I would like to have a simple input that accepts only numbers.
I created this directive :
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: 'input[numbersOnly]'
})
export class NumberDirective {
constructor(private _el: ElementRef) { }
@HostListener('input', ['$event']) onInputChange(event) {
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
if ( initalValue !== this._el.nativeElement.value) {
event.stopPropagation();
}
}
}
The issue I'm facing is that the "event.stopPropagation()" does not stop the event propagation, an event is fired even if the input value does not change from the user point of view.
How can I stop the event propagation when the field value has not changed ?
Edit : For better understanding, here is a stackblitz example : https://stackblitz.com/edit/angular-numbers-only-directive
I don't really think there is a way to stop this event using directive with
HostListener
.Angular detected this event before you listener was called so stopping propagation will not affect Angular events like(no proof for that so I may be wrong)ngModelChange
to which you react in parent component.I would suggest to provide own event indicating value change and emit it when you really want it to be emitted:
Then you can replace
ngModelChanged
binding withnumberChanged
:Demo: https://stackblitz.com/edit/angular-numbers-only-directive-a2mv6e
For usage in reactive forms, I ended up making a custom component implementing
ControlValueAccessor
:The component declaration (extract) :
Usage :
Here is the stackblitz.