Allowing the user to input number only is working.
But if the user tries to enter something other than number it must show message.
I have tried Validators with pattern, but I can't make the message show.
How to show error message when user doesn't enter a number?
.html file
<h3>Template Driven Form</h3>
<form #form="ngForm">
<input name="number" type="text" onlyNumber [(ngModel)]="number" />
<p>model value: {{ number }}</p>
<p>form dirty: {{ form.dirty }}</p>
</form>
<h3>Reactive Form</h3>
<form [formGroup]="formGroup">
<input formControlName="number" type="text" onlyNumber />
<p>model value: {{ formGroup.get('number').value }}</p>
<p>form dirty: {{ formGroup.dirty }}</p>
<!-- <div *ngIf="methoddd()">Sorry</div>
</form> -->
</form>
.ts file
import { Directive, ElementRef, forwardRef, HostListener, Renderer2 } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Directive({
selector: '[onlyNumber]',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => OnlyNumberDirective),
multi: true
}]
})
export class OnlyNumberDirective implements ControlValueAccessor {
private onChange: (val: string) => void;
private onTouched: () => void;
private value: string;
constructor(
private elementRef: ElementRef,
private renderer: Renderer2
) {
}
@HostListener('input', ['$event.target.value'])
onInputChange(value: string) {
const filteredValue: string = filterValue(value);
this.updateTextInput(filteredValue, this.value !== filteredValue);
}
@HostListener('blur')
onBlur() {
this.onTouched();
}
private updateTextInput(value: string, propagateChange: boolean) {
this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
if (propagateChange) {
this.onChange(value);
}
this.value = value;
}
// ControlValueAccessor Interface
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', isDisabled);
}
writeValue(value: any): void {
value = value ? String(value) : '';
this.updateTextInput(value, false);
}
}
function filterValue(value): string {
return value.replace(/[^0-9]*/g, '');
}
In your directive, you need to get references to form control via ngModel
and ngControl
, and then you need to set errors manually, and also you need to set previous value to form control to prevent it from changing.
In general, this is a job for custom validators, not a directive.
Try this:
<h3>Template Driven Form</h3>
<form #form="ngForm">
<input name="number" type="text" onlyNumber [(ngModel)]="number" />
<div *ngIf="!form.valid">{{form.controls.number.errors| json}}</div>
<p>form dirty: {{ form.dirty }}</p>
</form>
<h3>Reactive Form</h3>
<form [formGroup]="formGroup">
<input formControlName="number" type="text" onlyNumber />
<p>model err: {{ formGroup.get('number').errors | json }}</p>
<p>model value: {{ formGroup.get('number').value }}</p>
<p>form dirty: {{ formGroup.dirty }}</p>
</form>
import { Directive, ElementRef, HostListener} from '@angular/core';
import { NgControl, NgModel } from '@angular/forms';
@Directive({
selector: '[onlyNumber]',
providers: [NgModel]
})
export class OnlyNumberDirective {
constructor(private el: ElementRef,private control : NgControl, private ngModel: NgModel) {
}
@HostListener('input', ['$event']) onChange($event: any) {
const initialValue = this.el.nativeElement.value;
const newValue = initialValue.replace(/[^0-9]*/g, '');
if ( initialValue !== newValue) {
$event.stopPropagation();
this.control.control.setValue(newValue)
this.control.control.setErrors({'err': 'only numbers allowed'});
this.ngModel.control.setErrors({'err': 'only numbers allowed'});
}
}
}