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
Course Search
Search across all chapters & stages
๐Ÿ“–

Search the course

Type any topic โ€” branching, stash, rebase, hooks โ€” and jump straight to that chapter.

merge branchesgit stashundo commitrebase