Form Validation
Basic Example
typescriptimport { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-basic-form',
template: `
<form [formGroup]="userForm" (ngSubmit)="onSubmit()"> <label for="username">Username:</label> <input id="username" formControlName="username" />
<div *ngIf="userForm.get('username')?.invalid && userForm.get('username')?.touched">
Username is required and must be at least 4 characters. </div>
<label for="email">Email:</label>
<input id="email" formControlName="email" />
<div *ngIf="userForm.get('email')?.invalid && userForm.get('email')?.touched">
Enter a valid email address.
</div>
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
`
})
export class BasicFormComponent {
userForm: FormGroup;
constructor(private fb: FormBuilder) {
this.userForm = this.fb.group({
username: ['', [Validators.required, Validators.minLength(4)]],
email: ['', [Validators.required, Validators.email]]
});
}
onSubmit() {
if (this.userForm.valid) {
console.log('Form Submitted:', this.userForm.value);
}
}
}
In this basic example, a reactive Angular form is created using FormBuilder and FormGroup to centralize state management. The username and email fields are assigned validators: Validators.required, Validators.minLength, and Validators.email, ensuring that the user provides valid input. The template binds the form controls using formControlName and conditionally displays error messages with *ngIf when a control is invalid and has been touched. This design pattern emphasizes component-based thinking, maintaining a clear one-way data flow while avoiding prop drilling and unnecessary re-renders.
Practical Example
typescriptimport { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'app-advanced-form',
template: `
<form [formGroup]="profileForm" (ngSubmit)="submitProfile()"> <label for="fullName">Full Name:</label> <input id="fullName" formControlName="fullName" />
<div *ngIf="profileForm.get('fullName')?.invalid && profileForm.get('fullName')?.touched">
Full Name is required and must be at least 4 characters. </div>
<label for="email">Email:</label>
<input id="email" formControlName="email" />
<div *ngIf="profileForm.get('email')?.invalid && profileForm.get('email')?.touched">
Enter a valid email address.
</div>
<label for="age">Age:</label>
<input id="age" type="number" formControlName="age" />
<div *ngIf="profileForm.get('age')?.invalid && profileForm.get('age')?.touched">
Age must be between 18 and 99.
</div>
<button type="submit" [disabled]="profileForm.invalid">Save</button>
</form>
`
})
export class AdvancedFormComponent implements OnInit {
profileForm: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.profileForm = this.fb.group({
fullName: ['', [Validators.required, Validators.minLength(4)]],
email: ['', [Validators.required, Validators.email]],
age: [null, [Validators.required, Validators.min(18), Validators.max(99)]]
});
this.profileForm.valueChanges.pipe(debounceTime(300)).subscribe(value => {
console.log('Form Changes:', value);
});
}
submitProfile() {
if (this.profileForm.valid) {
console.log('Profile Saved:', this.profileForm.value);
}
}
}
This advanced example demonstrates a more complex reactive form, including an age field validated with Validators.min and Validators.max. The valueChanges observable is used with debounceTime to monitor form changes efficiently, reducing unnecessary re-renders and improving performance. This approach aligns with Angular's lifecycle management, allowing developers to react to state changes without mutating state directly, thereby avoiding prop drilling and preserving a predictable data flow.
📊 Reference Table
Angular Element/Concept | Description | Usage Example |
---|---|---|
FormGroup | Container for multiple form controls | this.fb.group({fullName: ['', Validators.required]}) |
FormControl | Represents an individual form input | new FormControl('', Validators.email) |
FormBuilder | Service to simplify form creation | constructor(private fb: FormBuilder) |
valueChanges | Observable to track form value changes | this.profileForm.valueChanges.subscribe(value => ...) |
ngSubmit | Event triggered on form submission | <form (ngSubmit)="submitProfile()"> |
🧠 Test Your Knowledge
Test Your Knowledge
Challenge yourself with this interactive quiz and see how well you understand the topic
📝 Instructions
- Read each question carefully
- Select the best answer for each question
- You can retake the quiz as many times as you want
- Your progress will be shown at the top