I have setup the updateOn of my form on "blur" (ngOnInit):
this.formStepper = this._fb.group({
steps: this._fb.array([
this._fb.group({
email: [
this.formDataMail.dataValue,
{
updateOn: 'blur',
validators: [Validators.required, Validators.email],
},
],
}),
new FormGroup({}),
]),
});
To manually valid my input (ngAfterViewInit) :
fromEvent(this.emailInput.nativeElement, 'keyup')
.pipe(
filter(Boolean),
debounceTime(600),
distinctUntilChanged(),
tap((_) => {
this.formArray.at(0).get('email').updateValueAndValidity();
})
)
.subscribe();
This should update the form value and display an error according to my validators but instead of that my form value remains null until I blur.
this.formArray
.at(0)
.valueChanges.pipe(
takeUntil(this._onDestroy$),
tap((changes: string ) => {
// changes value is synchronized with blur action even if I call updateValueAndValidity function
})
)
.subscribe();
Why does updateValueAndValidity not update the value as mentioned ?
Thank you very much
As a workaround, I tried to update the value manually and mark the form as dirty to display errors message before the first blur action
fromEvent(this.emailInput.nativeElement, 'keyup')
.pipe(
filter(Boolean),
debounceTime(600),
distinctUntilChanged(),
tap((_) => {
this.formArray
.at(0)
.get('email')
.setValue(this.emailInput.nativeElement.value);
this.formArray.at(0).get('email').markAsDirty();
this.formArray.at(0).get('email').updateValueAndValidity();
})
)
.subscribe();
CodePudding user response:
I think this approach is far too complicated. I propose the following solution.
1.) Remove updateOn: 'blur'
this.formStepper = this._fb.group({
steps: this._fb.array([
this._fb.group({
email: [
this.formDataMail.dataValue,
{
validators: [Validators.required, Validators.email],
},
],
}),
new FormGroup({}),
]),
});
2.) Set up your errors to display when the input is touched (meaning on blur):
<mat-error *ngIf="formArray.at(0).get('email').hasError('email') && !formArray.at(0).get('email').hasError('required')">
Please enter a valid email address
</mat-error>
<mat-error *ngIf="formArray.at(0).get('email').hasError('required')">
Email is <strong>required</strong>
</mat-error>
3.) Subscribe to the changes of the input and mark the input as touched after 600ms of debounce time:
this.formArray.at(0).get('email').valueChanges.pipe(debounceTime(600)).subscribe(() => {
this.formArray.at(0).get('email').markAsTouched();
});