0

I have a simple reactive form like this:

initSignupForm() {
    return new FormGroup({
      firstName: new FormControl(this.formData.firstName, [
        Validators.required,
      ]),
      lastName: new FormControl(this.formData.lastName, [Validators.required]),
      userName: new FormControl(this.formData.userName, {
        validators: [Validators.required],
        asyncValidators: [
          this.authService.checkUserName.bind(this.authService),
        ],
        updateOn: 'submit',
      }),
      userEmail: new FormControl(this.formData.userEmail, {
        validators: [Validators.required, Validators.email],
        asyncValidators: [
          this.authService.checkUserEmail.bind(this.authService),
        ],
        updateOn: 'submit',
      }),
    });
  }

For the userName and userEmail I have an async validator (an api call to the backend). It works all fine.

For submitting the form I have the usual lines in the template:

<form [formGroup]="signupForm" (ngSubmit)="submitForm()">

and a submit button:

<button
    type="submit"
    kendoButton
    themeColor="primary"
    fillMode="solid"
    size="large"
  >
    Regisztráció
  </button>

The submitForm event looks like this:

submitForm() {
    this.signupForm.markAllAsTouched();
    if (this.signupForm.valid) {
      const user = this.signupForm.value;
      console.log(user);
    }
  }

The issue is, that after filling in the form (all fields), I hit enter, the async validators run and pass and I have to press enter one more time in order to get the form valid and submitting. This is because of the updateOn: 'submit' strategy.

After submitting, the control values get populated and the form gets valid. And only after that can the form really submitted and the data sent to the backend. Basically I have to click on the submit button twice.

How can I overcome this, but keep the submit strategy?

This must be related to the async validator, because if I remove this, I have to submit the form only once.

derstauner
  • 1,478
  • 2
  • 23
  • 44
  • Please review this tutorial what you are missing : https://indepth.dev/posts/1311/the-update-on-option-in-angular-forms – Sunil Kumar Mar 25 '23 at 11:41
  • I have already read this before asking. Nothing new, resp. no mentioning about async validators in this context. – derstauner Mar 25 '23 at 13:00

1 Answers1

0

Again I have to answer my own question.

If we have async validators, where the updateOn strategy is set to submit, Angular won't wait till all async validators are finished, but instead it will call your submit event immediatelly.

Here and here are some interesting stuff to read.

The solution is to listen to the statusChanges event in the common way:

this.signupForm.statusChanges.subscribe((res) => {
      if (this.signupForm.valid && !this.backToBasicData) {
        this.submitForm();
      }
    });

(In my case I have a multi-step-form, that's why I have an other check in it).

Now, this works as expected.

The flow is as following:

  1. user fills in the form and hits enter / the submit button
  2. the submit event fires and the form state is changed to pending
  3. it doesn't happen anything, because the form status is still pending or invalid
  4. if the form status is changed from pending to valid, the submit event fires again because of the subscription and data can send safely to backend
derstauner
  • 1,478
  • 2
  • 23
  • 44