Angular Forms and Validations
Estimated study time: 14 minutes. Two ways to build forms in Angular, and how to validate user input properly in each.
Angular offers two distinct approaches to building forms — Template-Driven Forms and Reactive Forms — each with its own way of handling structure and validation.
Template-Driven Forms
Defined mostly in the HTML template using ngModel, with Angular inferring the form's structure from the markup. Good fit for simple forms.
<form #loginForm="ngForm" (ngSubmit)="onSubmit(loginForm)">
<input name="email" [(ngModel)]="email" required email #emailField="ngModel">
<div *ngIf="emailField.invalid && emailField.touched">
Please enter a valid email.
</div>
<button type="submit" [disabled]="loginForm.invalid">Login</button>
</form>
Reactive Forms
Defined in the component class using FormGroup and FormControl, giving you full programmatic control — easier to test and better suited for complex, dynamic forms.
this.loginForm = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required, Validators.minLength(8)])
});
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<input formControlName="email">
<div *ngIf="loginForm.get('email')?.invalid && loginForm.get('email')?.touched">
Please enter a valid email.
</div>
<button type="submit" [disabled]="loginForm.invalid">Login</button>
</form>
Built-in Validators
Validators.required— field must not be empty.Validators.email— must match email format.Validators.minLength(n)/maxLength(n)— length constraints.Validators.pattern(regex)— must match a custom regular expression.
Custom Validators
function passwordsMatch(group: AbstractControl): ValidationErrors | null {
const pass = group.get('password')?.value;
const confirm = group.get('confirmPassword')?.value;
return pass === confirm ? null : { mismatch: true };
}
Template-Driven vs Reactive
| Aspect | Template-Driven | Reactive |
|---|---|---|
| Structure defined in | HTML template | Component class |
| Testability | Harder (needs DOM) | Easier (plain objects) |
| Best for | Simple forms | Complex, dynamic forms |
💡 Tip: Show validation messages only after a field has been touched or the form submitted — flashing errors before the user has even typed anything feels hostile, not helpful.