Validation ensures users provide correct, complete data before a form submits. This lesson covers Angular's built-in validators, combining them, and displaying errors clearly.
How Angular Validation Works
Every FormControl tracks its own validity by running one or more validator functions against its current value, each returning either null (valid) or an error object describing what failed. Angular ships common validators (required, email, minLength, and more) in the Validators class.
A FormGroup's overall validity is derived from its child controls, if any control is invalid, the whole group is invalid too.
Pass a single validator function or an array of validators when defining a control.
Validators.pattern accepts a regular expression (or string) to validate against.
Validators.compose combines multiple validators into a single function, mainly used internally.
Custom validator functions follow the exact same signature as built-in ones (covered in the next lesson).
Built-in Validators Cheatsheet
The validators shipped in the Validators class.
Validator
Checks
Validators.required
Value is not empty/null/undefined
Validators.requiredTrue
Value is exactly true (checkboxes)
Validators.email
Value matches an email address pattern
Validators.minLength(n)
String/array length is at least n
Validators.maxLength(n)
String/array length is at most n
Validators.min(n)
Numeric value is at least n
Validators.max(n)
Numeric value is at most n
Validators.pattern(re)
Value matches the given regular expression
Displaying Validation Errors
The errors object on an invalid control tells you exactly which validators failed, letting you show specific, helpful messages instead of a generic "invalid" notice.
<input formControlName="email" />
@if (form.get('email')?.invalid && form.get('email')?.touched) {
@if (form.get('email')?.hasError('required')) {
<p>Email is required.</p>
}
@if (form.get('email')?.hasError('email')) {
<p>Please enter a valid email address.</p>
}
}
Asynchronous Validators
Some validation requires a server round-trip, checking whether a username is already taken, for example. Async validators return an Observable or Promise instead of a synchronous result, and Angular marks the control PENDING while waiting.
Some validation rules depend on more than one field, confirming a password matches, or that an end date is after a start date. These are attached at the FormGroup level rather than on a single control.
Showing raw validator error keys directly to users instead of translating them into friendly messages.
Attaching a cross-field validator to an individual control instead of the parent FormGroup.
Not accounting for the PENDING status while an async validator is running, showing a stale valid/invalid state.
Forgetting that Validators.required treats 0 and false as valid (non-empty) values, unlike an empty string.
Key Takeaways
Angular's Validators class ships common synchronous validators like required, email, and minLength.
A control's errors object identifies exactly which validators are currently failing.
Async validators support server-side checks and mark the control PENDING while resolving.
Cross-field validation is attached at the FormGroup level, not on individual controls.
Pro Tip
Debounce async validators ({ updateOn: 'blur' } or combining with debounceTime on valueChanges) to avoid firing a server request on every keystroke while a user is still typing.
You now understand Angular form validation. Next, learn how to build your own reusable Custom Validators.