← Back to Chapters

Reactive Form Validation

? Reactive Form Validation

? Quick Overview

Reactive form validation in Angular lets you define validation rules programmatically using Validators. This gives you full control over how each form control behaves, making it ideal for complex and dynamic forms.

In a reactive form:

  • You create a FormGroup and FormControl objects in the TypeScript code.
  • You attach Angular's built-in Validators (like required, email, minLength).
  • You bind the form to the template using [formGroup] and formControlName.

? Key Concepts

  • FormGroup: A collection of form controls that represents the entire form.
  • FormControl: Tracks the value and validation state of a single form input.
  • Validators: Functions that check if the control value is valid (e.g., required, email, min length).
  • Errors Object: Holds which validation rules failed for a control.
  • Touched / Dirty: Flags that indicate if the user has interacted with the control.

? Syntax & Theory

Typical steps to build a reactive form with validation:

  1. Import FormGroup, FormControl and Validators from @angular/forms.
  2. Create a FormGroup instance and configure each control with its validators.
  3. Bind the FormGroup to the template using [formGroup].
  4. Bind each input to a control using formControlName.
  5. Display validation error messages using the control's errors and touched state.
  6. Disable the submit button when the overall form is invalid using [disabled]="userForm.invalid".

⚙️ Pattern: Define validations in TS ➜ Show messages in template

? Code Example: TypeScript (Component)

? View Code Example
// Define a reactive form with validation rules
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(3)]),
email: new FormControl('', [Validators.required, Validators.email])
});

submitForm() {
console.log('Form Submitted', this.userForm.value);
}
}

? Code Example: Template (HTML)

? View Code Example
<!-- Bind the reactive form and show validation messages -->
<form [formGroup]="userForm" (ngSubmit)="submitForm()">
<label>Name:</label>
<input type="text" formControlName="name">
<div class="error" *ngIf="userForm.get('name')?.errors && userForm.get('name')?.touched">
<span *ngIf="userForm.get('name')?.errors?.required">Name is required.</span>
<span *ngIf="userForm.get('name')?.errors?.minlength">Name must be at least 3 characters.</span>
</div>
<br><br>

<label>Email:</label>
<input type="email" formControlName="email">
<div class="error" *ngIf="userForm.get('email')?.errors && userForm.get('email')?.touched">
<span *ngIf="userForm.get('email')?.errors?.required">Email is required.</span>
<span *ngIf="userForm.get('email')?.errors?.email">Invalid email format.</span>
</div>
<br><br>

<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

? What Happens When You Use This Form?

  • Name must not be empty and must have at least 3 characters.
  • Email must not be empty and must match a valid email format.
  • Error messages appear only when a field is both invalid and has been touched (user focused and left the field).
  • The Submit button stays disabled until the entire userForm is valid.
  • On submit, the form values are logged using console.log.

✅ Tips & Best Practices

  • Combine multiple validators on a single control for stronger rules (e.g., required + minlength).
  • Use userForm.get('controlName') to access the state, value, and errors of any control.
  • Use touched or dirty flags to avoid showing errors before the user interacts.
  • Keep validation messages short, clear, and specific to each rule.
  • Always import ReactiveFormsModule in your feature or root module before using reactive forms.
  • Group related controls in nested FormGroups for complex forms (e.g., address, profile).

? Try It Yourself

  • Add a password field with Validators.required and Validators.minLength(6).
  • Implement a confirm password field and a custom validator on the FormGroup to ensure both passwords match.
  • Show live validation messages as the user types (use the valueChanges observable).
  • Add a new control for age and validate it using a custom validator that checks for a minimum age (e.g., 18+).