Loading...

Form Validation

Basic Example

typescript
TYPESCRIPT Code
import { 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

typescript
TYPESCRIPT Code
import { 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

Ready to Start

Test Your Knowledge

Challenge yourself with this interactive quiz and see how well you understand the topic

4
Questions
🎯
70%
To Pass
♾️
Time
🔄
Attempts

📝 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