{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreig3rff3refoyucn75grnfy3yaf332n2xhvhpxpiqyfzk2oyy7hfba",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mpf6a35rqrn2"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreiddeasg44pkcdifepolpvdswuj3aqvasguryq3k4mcyt6nhkik4gq"
},
"mimeType": "image/webp",
"size": 64532
},
"path": "/alkademy/angular-reactive-forms-validation-complete-guide-2026-l69",
"publishedAt": "2026-06-28T23:10:23.000Z",
"site": "https://dev.to",
"tags": [
"angular",
"forms",
"validation",
"typescript",
"munonye.com",
"StackBlitz",
"Part 2 on munonye.com",
"munonye.com/angular-reactive-forms-validation-complete-guide-2026/",
"@angular",
"@Component"
],
"textContent": "> **Canonical URL:** Republished from munonye.com. Try the live demo: StackBlitz\n\n## Overview\n\nComplete guide to **Angular reactive forms validation** with Angular 19: built-in validators, custom validators, cross-field checks, async validation, and FormArray.\n\n**Prerequisites:** Basic reactive forms (Part 2 on munonye.com)\n\n**Estimated time:** ~50 minutes\n\n## Step 1 — Setup (standalone)\n\n\n import { Component, inject } from '@angular/core';\n import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';\n\n @Component({\n selector: 'app-signup',\n standalone: true,\n imports: [ReactiveFormsModule],\n templateUrl: './signup.component.html'\n })\n export class SignupComponent {\n private fb = inject(FormBuilder);\n form = this.fb.group({\n email: ['', [Validators.required, Validators.email]],\n password: ['', [Validators.required, Validators.minLength(8)]],\n confirmPassword: ['', Validators.required]\n });\n }\n\n\n## Step 2 — Display errors\n\n\n <input formControlName=\"email\">\n <span *ngIf=\"form.get('email')?.invalid && form.get('email')?.touched\">\n Enter a valid email\n </span>\n\n\nCall `this.form.markAllAsTouched()` on failed submit.\n\n## Step 3 — Custom validator\n\n\n export function noWhitespace(): ValidatorFn {\n return (control) => {\n const v = (control.value || '').trim();\n return v.length ? null : { whitespace: true };\n };\n }\n\n\n## Step 4 — Password match (cross-field)\n\n\n function passwordMatch(group: AbstractControl): ValidationErrors | null {\n const pass = group.get('password')?.value;\n const confirm = group.get('confirmPassword')?.value;\n return pass === confirm ? null : { passwordMismatch: true };\n }\n\n form = this.fb.group({ password: [''], confirmPassword: [''] }, { validators: passwordMatch });\n\n\n## Step 5 — Async validator\n\n\n username: ['', [Validators.required], [usernameTakenValidator]]\n\n\nShow `<span *ngIf=\"form.get('username')?.pending\">Checking…</span>` while pending.\n\n**Full guide with FormArray, dynamic validators, and FAQ:** munonye.com/angular-reactive-forms-validation-complete-guide-2026/",
"title": "Angular Reactive Forms Validation — Complete Guide (2026)"
}