1. Template-driven Forms
Template-driven forms are simple and rely on directives in the template.
1.1 ngModel
Bind form input values to component properties using ngModel.
<form #userForm="ngForm" (ngSubmit)="submitForm(userForm)">
<input name="username" [(ngModel)]="username" placeholder="Username" required>
<button type="submit">Submit</button>
</form>
username = '';
submitForm(form: any) {
console.log(form.value);
}
1.2 Form Validation
Add validation attributes like required, minlength, email.
<input name="email" [(ngModel)]="email" required email>
1.3 Form Errors
Show validation errors in the template:
<div *ngIf="email.invalid && email.touched">
<small *ngIf="email.errors?.required">Email is required</small>
<small *ngIf="email.errors?.email">Invalid email format</small>
</div>
2. Reactive Forms
Reactive forms give more control and are defined entirely in TypeScript.
2.1 FormGroup & FormControl
import { FormGroup, FormControl } from '@angular/forms';
userForm = new FormGroup({
username: new FormControl(''),
email: new FormControl('')
});
<form [formGroup]="userForm" (ngSubmit)="submitReactiveForm()">
<input formControlName="username" placeholder="Username">
<input formControlName="email" placeholder="Email">
<button type="submit">Submit</button>
</form>
2.2 FormBuilder
Simpler way to create reactive forms:
import { FormBuilder, Validators } from '@angular/forms';
constructor(private fb: FormBuilder) { }
userForm = this.fb.group({
username: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
2.3 Custom Validators
Create a function to validate form controls:
import { AbstractControl, ValidationErrors } from '@angular/forms';
function noSpaceValidator(control: AbstractControl): ValidationErrors | null {
if (control.value && control.value.indexOf(' ') >= 0) {
return { noSpace: true };
}
return null;
}
Add to a form control:
username: ['', [Validators.required, noSpaceValidator]]
2.4 Async Validators
Used for server-side validation like checking username availability:
import { AsyncValidatorFn } from '@angular/forms';
import { of } from 'rxjs';
import { delay, map } from 'rxjs/operators';
function asyncValidator(): AsyncValidatorFn {
return (control) => {
return of(control.value).pipe(
delay(1000),
map(value => value === 'admin' ? { forbiddenName: true } : null)
);
};
}
2.5 Reactive Form Validation Messages
Display errors dynamically:
<div *ngIf="userForm.get('username').invalid && userForm.get('username').touched">
<small *ngIf="userForm.get('username').errors?.required">Username is required</small>
<small *ngIf="userForm.get('username').errors?.noSpace">No spaces allowed</small>
</div>
Summary
- Angular provides template-driven and reactive forms
- Template-driven forms use
ngModel and validations in HTML - Reactive forms are defined in TypeScript using
FormGroup, FormControl, and FormBuilder - Both support custom validators, async validators, and dynamic error messages
- Reactive forms are preferred for complex and large-scale applications