Home > Enterprise >  UpdateValueAndValidity does not update the form value
UpdateValueAndValidity does not update the form value

Time:01-20

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();
    });

StackBlitz here.

  • Related