Triggering Validation in Angular's Reactive Forms

Trigger Form Validation When Input Changes

Today with my friend @alt148 I was playing with Dynamic Forms, and we discovered changing one form control can trigger the validation several times in the validation process. For example, we have a form with a field, and in every key press, the form validation is listened to by him and triggers de validations.

It is a bit annoying because if you have some UI and react every time the form trigger validation is not lovely, let's create a scenario:

Scenario

We have a form and want to show the message when the form is valid.

 formOne = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.email]),
    name: new FormControl('', [Validators.required]),
  });

  formOneStatus$ = this.formOne.statusChanges.pipe(
    map((v) => v + Date.now().toString())
  );

To watch how often the validation is triggered, we subscribe to the form statusChanges. Be aware not all validations are triggerd, just the validation of the form control you are changing. It casts the outcome to the form group validation property. So not all validations of a form are triggered. But the status change will emit a value every time, on each form control that receives input changes.

We add the date to the different times

My form status {{ formOneStatus$ | async }}
<form [formGroup]="formOne">
  Name:<input formControlName="name" type="text" /> Email:<input
    formControlName="email"
    type="text"
  />
</form>

Every time we press a key, the validation is triggered, hitting the performance and the user experience because the user starts to see the invalid or valid in every key press.

multipletimes.gif

Change the Default Form Behavior

Luckily, we're reading the official Angular documentation about the reactive angular forms trigger validation for every change in the form.

Angular provides an option to change the default behavior. We have three options:

  • 'change' is the default, and listening for every change.
  • 'blur' on blur event in the input.
  • 'submit' when submitting the form.

We add an extra object in the form group declaration with the property updateOn with the blur value.

formOne = new FormGroup(
    {
      email: new FormControl('', [Validators.required, Validators.email]),
      name: new FormControl('', [Validators.required]),
    },
    {
      updateOn: 'blur',
    }
  );

It makes our form continues working and only trigger the validation when on the blur event and not in every key press.

less.gif

Note: be careful because if you use some elements without blur, it does not trigger the changes.

Feel free to play in the online demo in stackbliz