Angular Custom Validators का use तब किया जाता है जब built-in validators आपकी business requirements को पूरा नहीं करते। Real-world applications में अक्सर ऐसी validation logic चाहिए होती है जो simple required, email या minLength से कहीं ज्यादा complex होती है। Angular आपको synchronous और asynchronous दोनों तरह के custom validators बनाने की पूरी flexibility देता है।
इस chapter में हम custom validators को step-by-step, Reactive Forms के perspective से deep में समझेंगे, साथ ही Template-Driven Forms में उनका limited use भी cover करेंगे।
Custom Validator क्या होता है
Custom Validator एक function होता है जो:
- FormControl या FormGroup को input के रूप में लेता है
- Validation result return करता है
- Control की
errorsproperty को set करता है
अगर validation pass होती है तो null return किया जाता है।
अगर validation fail होती है तो error object return किया जाता है।
Custom Validator का Basic Structure
Synchronous custom validator का basic structure:
import { AbstractControl, ValidationErrors } from '@angular/forms';
export function customValidator(
control: AbstractControl
): ValidationErrors | null {
if (/* invalid condition */) {
return { customError: true };
}
return null;
}
Angular internally इस return value के basis पर control को valid या invalid mark करता है।
Simple Custom Validator Example
मान लेते हैं कि username में spaces allow नहीं हैं।
Validator Function
import { AbstractControl, ValidationErrors } from '@angular/forms';
export function noSpaceValidator(
control: AbstractControl
): ValidationErrors | null {
if (!control.value) {
return null;
}
const hasSpace = control.value.includes(' ');
return hasSpace ? { noSpace: true } : null;
}
Reactive Form में Use करना
import { FormControl } from '@angular/forms';
import { noSpaceValidator } from './no-space.validator';
username = new FormControl('', [noSpaceValidator]);
Template में Error Show करना
<div *ngIf="username.errors?.['noSpace']">
Spaces are not allowed
</div>
Validators के Error Object को समझना
Error object का structure fully developer-controlled होता है।
return {
passwordStrength: {
minLength: 8,
hasNumber: false
}
};
Template में access:
<div *ngIf="control.errors?.['passwordStrength']">
Weak password
</div>
यह flexibility complex error messages बनाने में बहुत useful है।
Parameterized Custom Validators
अक्सर validator को parameters की जरूरत होती है।
Example: minimum age validator।
Validator Factory Function
export function minAgeValidator(minAge: number) {
return (control: AbstractControl): ValidationErrors | null => {
if (!control.value) {
return null;
}
return control.value < minAge
? { minAge: { requiredAge: minAge } }
: null;
};
}
Use in FormControl
age = new FormControl('', [minAgeValidator(18)]);
Error Message
<div *ngIf="age.errors?.['minAge']">
Minimum age is {{ age.errors?.['minAge'].requiredAge }}
</div>
FormGroup Level Custom Validators
कुछ validations एक single field पर नहीं, बल्कि multiple fields पर depend करती हैं।
Example: password और confirm password match validation।
Group Validator Function
import { AbstractControl, ValidationErrors } from '@angular/forms';
export function passwordMatchValidator(
group: AbstractControl
): ValidationErrors | null {
const password = group.get('password')?.value;
const confirm = group.get('confirmPassword')?.value;
if (password !== confirm) {
return { passwordMismatch: true };
}
return null;
}
Apply करना FormGroup पर
this.form = this.fb.group(
{
password: [''],
confirmPassword: ['']
},
{ validators: passwordMatchValidator }
);
Template में Check करना
<div *ngIf="form.errors?.['passwordMismatch']">
Passwords do not match
</div>
Control vs Group Validator Difference
- Control validator → single input logic
- Group validator → multiple inputs dependency
Wrong level पर validator लगाने से validation work नहीं करती, यह beginners की common mistake है।
Asynchronous Custom Validators
जब validation server call या async operation पर depend करती है, तब async validators use किए जाते हैं।
Example: username availability check।
Async Validator Function
import { AbstractControl, ValidationErrors } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { delay, map } from 'rxjs/operators';
export function usernameTakenValidator(
control: AbstractControl
): Observable<ValidationErrors | null> {
if (!control.value) {
return of(null);
}
return of(control.value).pipe(
delay(1000),
map(value =>
value === 'admin' ? { usernameTaken: true } : null
)
);
}
Apply Async Validator
username = new FormControl(
'',
[],
[usernameTakenValidator]
);
Angular automatically async validator की lifecycle handle करता है।
Async Validation States
Async validators के दौरान control state:
pending→ validation in progressvalid/invalid→ result after completion
Template example:
<div *ngIf="username.pending">
Checking availability...
</div>
Template-Driven Forms में Custom Validators
Template-driven forms में custom validators directive के रूप में बनते हैं।
High-level concept:
Validatorinterface implement करनाNG_VALIDATORSprovide करना
यह approach ज्यादा boilerplate-heavy होती है, इसलिए complex validation के लिए Reactive Forms recommended हैं।
Reusable Validator Strategy
Large projects में validators को organize करना जरूरी है।
Best practices:
- Validators को separate files में रखें
- Domain-specific validators group करें
- Naming clear और consistent रखें
- Validators में UI logic न डालें
Example structure:
- validators/
- password.validators.ts
- user.validators.ts
Common Mistakes
- Validator में side effects करना
- Direct DOM access
- Validation logic template में लिखना
- Async validator को sync की तरह treat करना
- Group-level validation को control पर apply करना
Custom Validators क्यों जरूरी हैं
Angular Custom Validators आपको:
- Business rules enforce करने देते हैं
- Clean और reusable validation logic देते हैं
- Forms को production-ready बनाते हैं
- Backend validation के साथ align करते हैं
Custom Validators Angular Forms का सबसे powerful हिस्सा हैं। अगले chapter में हम Dynamic Forms को cover करेंगे, जहाँ validators dynamically add और remove करना एक core requirement बन जाता है।
