Reactive Forms
Written By: Avinash Malhotra
Updated on
Reactive Form are types Angular Forms which works on model-driven approach to manage form data. Reactive Forms has Strong Data Model in form of FormControl object, which gives clear control and easy validation. Also we can create dynamic forms and update controls on runtime. Reactive form also easy to test.
Create Reactive Form
To create reactive form, first import ReactiveFormsModule
in app.component.ts file. Also include FormControl
,FormGroup
and FormArray
classes in the component.
/* app.component.ts */
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { FormControl, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet,FormsModule,CommonModule,ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent{
title = 'myApp';
}
/* app.component.html */
<h1>{{title}}</h1>
<form novalidate>
<label>Email: <input type="email" name="email"></label>
<label>Password: <input type="password" name="email" ></label>
</form>
Form Control
FormControl class is added to one single form control to track its value and validity. We can create multiple FormControl for various input fields in form.
To view value of controls, use <output>
with values.
/* app.component.ts */
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { FormControl, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet,FormsModule,CommonModule,ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent{
title = 'myApp';
email=new FormControl('');
}
/* app.component.html */
<h1>{{title}}</h1>
<form novalidate>
<label>Email: <input type="email" name="email" [formControl]="email"></label>
<output>{{email.value}}</output>
</form>
Form Group
To use multiple form controls, use FormGroup class . FromGroup groups multiple FormControls and also track the validity and values of form or form controls group.
/* app.component.ts */
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { FormControl, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet,FormsModule,CommonModule,ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent{
title = 'myApp';
loginform=new FormGroup({
email:new FormControl(""),
pass:new FormControl("")
});
loginUser(){
console.log(this.loginform.status);
console.log(this.loginform.value);
console.log(this.loginform.valid);
};
}
/* app.component.html */
<h1>{{title}}</h1>
<form novalidate [formGroup]="loginform" (ngSubmit)="loginUser()">
<label>Email: <input type="email" name="email" formControlName="email"></label>
<label>Password: <input type="password" name="email"formControlName="pass"></label>
<button>Send</button>
<p>{{loginform.value | json}}</p>
<p>{{loginform.statue}}</p>
<p>{{loginform.valid}}</p>
</form>
Validator
To validate controls in Reactive Form, import class Validators in component. We can choose type of validation based on required, minlength or pattern.
For validation outputs, we can use hasError or invalid property in template.
Reactive Form Validation Example
/* app.component.ts */
import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { Validators } from '@angular/forms';
import { FormControl, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet,FormsModule,CommonModule,ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent{
title = 'myApp';
loginform=new FormGroup({
email:new FormControl(null,[Validators.required, Validators.minLength(3)]),
pass:new FormControl(null, [Validators.required, Validators.minLength(6)])
});
loginUser(){
console.log(this.loginform.status);
console.log(this.loginform.value);
console.log(this.loginform.valid);
};
}
/* app.component.html */
<h1>{{title}}</h1>
<form novalidate [formGroup]="loginform" (ngSubmit)="loginUser()">
<label>Email: <input type="email" name="email" formControlName="email">
<span *ngIf="loginform.get('email')?.hasError('required') && loginform.get('email')?.pristine"> Email Required</span>
<span *ngIf="loginform.get('email')?.invalid && loginform.get('email')?.dirty"> Email Invalid</span>
</label>
<label>Password: <input type="password" name="email" formControlName="pass">
<span *ngIf="loginform.get('pass')?.invalid && loginform.get('pass')?.pristine"> Password Required</span>
<span *ngIf="!loginform.get('pass')?.valid && loginform.get('pass')?.dirty"> Password Invalid</span>
</label>
<button>Send</button>
<p>{{loginform.value | json}}</p>
<p>{{loginform.statue}}</p>
<p>{{loginform.valid}}</p>
</form>
FormBuilder
FormBuilder makes it easier to handle long forms with more inputs controls by simplifying syntax of FormControl and FormGroup.
To use FormBuilder, first import FormBuilder in component file. Now inject it to the component class as shown below.
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { FormBuilder } from '@angular/forms';
import { Validators } from '@angular/forms';
import { FormControl, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet,FormsModule,CommonModule,ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent{
title = 'myApp';
constructor(private fb:FormBuilder){ }
loginForm:FormGroup=this.fb.group({
email:['',[Validators.required,Validators.minLength(4)]],
pass:['',[Validators.required, Validators.minLength(6)]],
});
}
<form novalidate [formGroup]="loginForm">
<label>Email: <input type="email" name="email" required formControlName="email"></label>
<label>Password: <input type="password" name="pass" required formControlName="pass"></label>
<p> {{loginForm.value | json}}</p>
<p>{{loginForm.valid}}</p>
</form>
update model using setValue and patchValue
setValue and patchValue is used to update the value of single form control or formGroup in reactive form.
setValue
setValue set new value of form controls or formGroup. use setValue when wen want to set Entire form controls.
patchValue
patchValue patch new values of individual or more form controls.
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import { FormBuilder } from '@angular/forms';
import { Validators } from '@angular/forms';
import { FormControl, FormArray, FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
standalone: true,
imports: [RouterOutlet,FormsModule,CommonModule,ReactiveFormsModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent{
title = 'myApp';
constructor(private fb:FormBuilder){ }
loginForm:FormGroup=this.fb.group({
email:['',[Validators.required,Validators.minLength(4)]],
pass:['',[Validators.required, Validators.minLength(6)]],
});
setVal(){this.loginForm.setValue({email:"aa@bb",pass:'1234'})}
patchVal(){this.loginForm.patchValue({email:"aa@bb"})}
}
<form novalidate [formGroup]="loginForm">
<label>Email: <input type="email" name="email" required formControlName="email"></label>
<label>Password: <input type="password" name="pass" required formControlName="pass"></label>
<button (click)="setVal()"> Set </button>
<button (click)="patchVal()"> Patch </button>
<p> {{loginForm.value | json}}</p>
<p>{{loginForm.valid}}</p>
</form>