Reactive Forms in Angular
Reactive forms in Angular provide a model-driven approach to handling form inputs and validations. This tutorial covers the basics of reactive forms and how to use them effectively in your Angular applications.
What are Reactive Forms?
Reactive forms are highly scalable and reusable forms built using a model-driven approach. They provide more control over the form's state and validations through the use of Angular's FormControl
, FormGroup
, and FormArray
classes.
Setting Up Reactive Forms
To set up reactive forms, you need to import the ReactiveFormsModule
in your application module:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, ReactiveFormsModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Creating a Reactive Form
Here is an example of a simple reactive form:
// app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userForm = new FormGroup({
name: new FormControl('', [Validators.required]),
email: new FormControl('', [Validators.required, Validators.email])
});
onSubmit() {
console.log('Form submitted!', this.userForm.value);
}
}
// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div>
<label for="name">Name</label>
<input type="text" id="name" formControlName="name">
<div *ngIf="userForm.get('name').invalid && userForm.get('name').touched">Name is required</div>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" formControlName="email">
<div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">Enter a valid email</div>
</div>
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
Form Validation
Reactive forms support built-in validators such as required
, minlength
, maxlength
, pattern
, etc. Custom validators can also be created if needed:
// app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(3)]),
email: new FormControl('', [Validators.required, Validators.email])
});
onSubmit() {
console.log('Form submitted!', this.userForm.value);
}
}
// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div>
<label for="name">Name</label>
<input type="text" id="name" formControlName="name">
<div *ngIf="userForm.get('name').invalid && userForm.get('name').touched">
<div *ngIf="userForm.get('name').errors.required">Name is required</div>
<div *ngIf="userForm.get('name').errors.minlength">Name must be at least 3 characters long</div>
</div>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" formControlName="email">
<div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">
<div *ngIf="userForm.get('email').errors.required">Email is required</div>
<div *ngIf="userForm.get('email').errors.email">Invalid email format</div>
</div>
</div>
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
Form Groups and Form Arrays
Reactive forms allow you to group controls together using FormGroup
and FormArray
for managing complex forms:
// app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
userForm = new FormGroup({
name: new FormControl('', [Validators.required]),
email: new FormControl('', [Validators.required, Validators.email]),
addresses: new FormArray([
new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl('')
})
])
});
get addresses() {
return (this.userForm.get('addresses') as FormArray).controls;
}
addAddress() {
const addressForm = new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
state: new FormControl('')
});
(this.userForm.get('addresses') as FormArray).push(addressForm);
}
onSubmit() {
console.log('Form submitted!', this.userForm.value);
}
}
// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
<div>
<label for="name">Name</label>
<input type="text" id="name" formControlName="name">
<div *ngIf="userForm.get('name').invalid && userForm.get('name').touched">Name is required</div>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" formControlName="email">
<div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">Email is required</div>
</div>
<div formArrayName="addresses">
<div *ngFor="let address of addresses; let i = index" [formGroupName]="i">
<h4>Address {{ i + 1 }}</h4>
<label for="street">Street</label>
<input type="text" formControlName="street">
<label for="city">City</label>
<input type="text" formControlName="city">
<label for="state">State</label>
<input type="text" formControlName="state">
</div>
</div>
<button type="button" (click)="addAddress()">Add Address</button>
<button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>
Key Points
- Reactive forms are built using a model-driven approach and provide more control over the form's state and validations.
- Use the
ReactiveFormsModule
to set up reactive forms in your application module. - Reactive forms support built-in validators and allow you to create custom validators as needed.
- Use
FormGroup
andFormArray
to manage complex forms with multiple controls. - Reactive forms provide better scalability and reusability for handling form inputs and validations.
Conclusion
Reactive forms in Angular offer a powerful and flexible way to handle form inputs and validations. By understanding and using reactive forms effectively, you can create robust and dynamic forms in your Angular applications. Happy coding!