Chapter 8.4☕ 15 min read

Built-in Validators

Validators check if a form control's value is valid. Angular provides ready-made validators for common rules: required, length, range, pattern, and email.

01What are Validators

Validators are functions that check if a control's value meets certain rules. They return null if valid, or an error object if invalid.

// Valid — returns null
Validators.required(new FormControl('Hello'))  → null

// Invalid — returns error object
Validators.required(new FormControl(''))  → { required: true }

// Invalid with details
Validators.minLength(3)(new FormControl('ab'))  → { minlength: { requiredLength: 3, actualLength: 2 } }

"Validator = quality check — biryani tik hai ya nahi."

Two types of validators:

  • Sync — instant, return result immediately (required, email, pattern)
  • Async — need to call server, return Observable (username taken, credit card valid)

This chapter covers sync validators. Async validators are in the next chapter.

02Common Sync Validators

Angular provides these built-in sync validators:

import { Validators } from '@angular/forms';

// Required — field must have value (not null/undefined/empty)
Validators.required

// String length
Validators.minLength(3)  // Minimum 3 characters
Validators.maxLength(50) // Maximum 50 characters

// Numeric range
Validators.min(1)    // Minimum value (inclusive)
Validators.max(999)  // Maximum value (inclusive)

// Format
Validators.email     // Must be valid email format
Validators.pattern('[a-zA-Z ]*')  // Must match regex

// Composite
Validators.requiredTrue  // Value must be true (for checkboxes)

"Built-in validators = ready-made tests — import aur use karo."

Don't reinvent the wheel — these cover 90% of common validation needs.

03Applying Validators

Validators are applied in the second argument of FormControl or FormBuilder array syntax.

Single validator:

name: ['', Validators.required]

// Or with FormBuilder
name: ['', [Validators.required]]

Multiple validators (array):

name: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(50)]]

price: [0, [Validators.required, Validators.min(1), Validators.max(10000)]]

email: ['', [Validators.required, Validators.email]]

On FormGroup level (cross-field validation):

this.fb.group({
  password: ['', [Validators.required, Validators.minLength(8)]],
  confirmPassword: ['', Validators.required],
}, { validators: passwordMatchValidator }); // ← Group level validator

On FormArray:

skills: this.fb.array([
  this.fb.control('', Validators.required) // Each skill is required
], { validators: minLengthArrayValidator(1) }) // Array must have at least one

"Single ya multiple — array mein daal do."

04Showing Validation Errors in Template

Showing validation errors is a critical UX pattern — only show errors AFTER the user has interacted with the field.

@if (name.invalid && (name.touched || name.dirty)) {
  @if (name.errors?.['required']) {
    <small class="error">Naam zaruri hai bhai</small>
  }
  @if (name.errors?.['minlength']) {
    <small class="error">Kam se kam {{ name.errors?.['minlength'].requiredLength }} characters chahiye</small>
  }
  @if (name.errors?.['maxlength']) {
    <small class="error">Zyaada se zyaada {{ name.errors?.['maxlength'].requiredLength }} characters</small>
  }
}

"Error pehle se mat dikhao — user ne type kiya tab dikhao."

Best practice — create a helper getter:

get nameControl() { return this.form.get('name')!; }
get emailControl() { return this.form.get('email')!; }

// Then in template:
@if (nameControl.invalid && nameControl.touched) { ... }

Error order matters! Show errors in this priority: required first, then format/pattern, then other validations. Because if a field is empty, there's no value to validate format against.

05Validation CSS Classes

Angular automatically adds CSS classes to form controls based on their state — no manual class binding needed.

// Angular auto-applies these classes:
// Initial state
.ng-pristine.ng-untouched.ng-valid

// After user types
.ng-dirty.ng-untouched.ng-valid

// After user clicks away (touched)
.ng-dirty.ng-touched.ng-valid

// If validation fails
.ng-dirty.ng-touched.ng-invalid

"Automatic CSS classes — Angular tumhare liye classes lagata hai."

Style accordingly:

/* Default — no validation styling */
input { border: 1px solid #ccc; }

/* Invalid and user has interacted — show red */
input.ng-invalid.ng-touched {
  border-color: #f38ba8;
  background: rgba(243, 139, 168, 0.05);
}

/* Valid and user has interacted — show green */
input.ng-valid.ng-touched {
  border-color: #a6e3a1;
}

/* Show error message container only when needed */
.error-message { display: none; }
.ng-invalid.ng-touched ~ .error-message { display: block; }

These classes are framework-agnostic — they work with any CSS framework (Bootstrap, Tailwind, Material).

Key Takeaways

  • ✅ Validators return null if valid, error object if invalid — { required: true, minlength: {...} }
  • ✅ Built-in: required, minLength, maxLength, min, max, email, pattern, requiredTrue
  • ✅ Apply as array: [Validators.required, Validators.minLength(3)]
  • ✅ Show errors ONLY after touched/dirty — never show on pristine untouched fields
  • ✅ Angular auto-adds CSS classes: .ng-valid, .ng-invalid, .ng-touched, .ng-dirty