Triggering Validation in Angular's Reactive Forms
Table of contents
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.
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.
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
Subscribe to my newsletter
Read articles from Dany Paredes directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Dany Paredes
Dany Paredes
I'm passionate about front-end development, specializing in building UI libraries and working with technologies like Angular, NgRx, Accessibility, and micro-frontends. In my free time, I enjoy writing content for the Google Dev Library, This Is Angular Community, Kendo UI, and sharing insights here.