Angular FormBuilder API makes it easier to build reactive forms. We can easily add the FormGroup, nested FormGroup’s, FormArray’s & FormControls easily. It also allows us to set up the Validation rules for each of the controls. In this tutorial, we will show you how to create a Form, add validation rules using the FormBuilder.
If you are new to Reactive Forms, we recommend you to learn how to build reactive forms.
The FormBuilder is the helper API to build forms in Angular. It provides shortcuts to create the instance of the FormControl, FormGroup or FormArray. It reduces the code required to write the complex forms.
To use the FormBuilder, first, we need to import it in our component
import { FormBuilder } from '@angular/forms'
Next, we need to inject it into our component class
constructor(private formBuilder: FormBuilder) {
}
Finally, use the group, array & control methods to build the FormModel
We use the group method to build the Form Group. We pass the list of Form Controls, Form Array, or anotherForm Groupto the group method as key-value pair. Where the key is the name of the FormControl,FormGroup or FormArray. The value is the configuration of the control.
In the following example, we have added six form controls. The First argument to the FormControl is the initial value, which we set to empty string.
this.contactForm = this.formBuilder.group({
firstname: [''],
lastname: [''],
email: [''],
gender: [''],
isMarried: [''],
country: [''],
});
Creating a Nested FormGroup is just as easy. use the formbuilder.group method, as shown below.
this.contactForm = this.formBuilder.group({
firstname: [''],
lastname: [''],
email: [''],
gender: [''],
isMarried: [''],
country: [''],
address: this.formBuilder.group({
city: [''],
street: [''],
pincode: ['']
})
})
The second argument to the FormControl is the list of sync validators. The following example shows how to add validators.
this.contactForm = this.formBuilder.group({
firstname: ['', [Validators.required, Validators.minLength(10)]],
lastname: ['', [Validators.required, Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]],
email: ['', [Validators.required, Validators.email]],
gender: ['', [Validators.required]],
isMarried: ['', [Validators.required]],
country: ['', [Validators.required]],
address: this.formBuilder.group({
city: ['', [Validators.required]],
street: ['', [Validators.required]],
pincode: ['', [Validators.required]],
})
});
We learned how to build reactive forms the Angular Reactive forms tutorial.
app.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms'
import { FormBuilder } from '@angular/forms'
import { groupBy } from 'rxjs/internal/operators/groupBy';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Angular Reactive forms';
contactForm;
constructor(private formBuilder: FormBuilder) {
// this.contactForm = this.formBuilder.group({
// firstname: [''],
// lastname: [''],
// email: [''],
// gender: [''],
// isMarried: [''],
// country: [''],
// });
// this.contactForm = this.formBuilder.group({
// firstname: [''],
// lastname: [''],
// email: [''],
// gender: [''],
// isMarried: [''],
// country: [''],
// address: this.formBuilder.group({
// city: [''],
// street: [''],
// pincode: ['']
// })
// });
this.contactForm = this.formBuilder.group({
firstname: ['', [Validators.required, Validators.minLength(10)]],
lastname: ['', [Validators.required, Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]],
email: ['', [Validators.required, Validators.email]],
gender: ['', [Validators.required]],
isMarried: ['', [Validators.required]],
country: ['', [Validators.required]],
address: this.formBuilder.group({
city: ['', [Validators.required]],
street: ['', [Validators.required]],
pincode: ['', [Validators.required]],
})
});
}
get firstname() {
return this.contactForm.get('firstname');
}
get lastname() {
return this.contactForm.get('lastname');
}
get email() {
return this.contactForm.get('email');
}
get gender() {
return this.contactForm.get('gender');
}
get isMarried() {
return this.contactForm.get('isMarried');
}
get country() {
return this.contactForm.get('country');
}
get city() {
return this.contactForm.get("address").get('city');
}
get street() {
return this.contactForm.get("address").get('street');
}
get pincode() {
return this.contactForm.get("address").get('pincode');
}
countryList: country[] = [
new country("1", "India"),
new country('2', 'USA'),
new country('3', 'England')
];
onSubmit() {
console.log(this.contactForm.value);
}
}
export class country {
id: string;
name: string;
constructor(id: string, name: string) {
this.id = id;
this.name = name;
}
}
<div style="float: left; width:50%;">
<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
<p>
<label for="firstname">First Name </label>
<input type="text" id="firstname" name="firstname" formControlName="firstname">
</p>
<div
*ngIf="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
<div [hidden]="!firstname.errors.required">
First Name is required
</div>
<div [hidden]="!firstname.errors.minlength">
Min Length is 10
</div>
</div>
<p>
<label for="lastname">Last Name </label>
<input type="text" id="lastname" name="lastname" formControlName="lastname">
</p>
<div *ngIf="!lastname.valid && (lastname.dirty ||lastname.touched)">
<div [hidden]="!lastname.errors.pattern">
Only characters are allowed
</div>
<div [hidden]="!lastname.errors.maxLength">
Max length allowed is {{lastname.errors.maxlength?.requiredLength}}
</div>
<div [hidden]="!lastname.errors.required">
Last Name is required
</div>
</div>
<p>
<label for="email">Email </label>
<input type="text" id="email" name="email" formControlName="email">
</p>
<div *ngIf="!email.valid && (email.dirty ||email.touched)">
<div [hidden]="!email.errors.required">
email is required
</div>
<div [hidden]="!email.errors.email">
invalid email id
</div>
</div>
<p>
<label for="gender">Geneder </label>
<input type="radio" value="male" id="gender" name="gender" formControlName="gender"> Male
<input type="radio" value="female" id="gender" name="gender" formControlName="gender"> Female
</p>
<div *ngIf="!gender.valid && (gender.dirty ||gender.touched)">
<div [hidden]="!gender.errors.required">
gender is required
</div>
</div>
<p>
<label for="isMarried">Married </label>
<input type="checkbox" id="isMarried" name="isMarried" formControlName="isMarried">
</p>
<div *ngIf="!isMarried.valid && (isMarried.dirty ||isMarried.touched)">
<div [hidden]="!isMarried.errors.required">
isMarried is required
</div>
</div>
<p>
<label for="country">country </label>
<select id="country" name="country" formControlName="country">
<option [ngValue]="c.id" *ngFor="let c of countryList">
{{c.name}}
</option>
</select>
</p>
<div *ngIf="!country.valid && (country.dirty ||country.touched)">
<div [hidden]="!country.errors.required">
country is required
</div>
</div>
<div formGroupName="address">
<div class="form-group">
<label for="city">City</label>
<input type="text" class="form-control" name="city" formControlName="city">
</div>
<div *ngIf="!city.valid && (city.dirty ||city.touched)">
<div [hidden]="!city.errors.required">
city is required
</div>
</div>
<div class="form-group">
<label for="street">Street</label>
<input type="text" class="form-control" name="street" formControlName="street">
</div>
<div *ngIf="!street.valid && (street.dirty ||street.touched)">
<div [hidden]="!street.errors.required">
street is required
</div>
</div>
<div class="form-group">
<label for="pincode">Pin Code</label>
<input type="text" class="form-control" name="pincode" formControlName="pincode">
</div>
<div *ngIf="!pincode.valid && (pincode.dirty ||pincode.touched)">
<div [hidden]="!pincode.errors.required">
pincode is required
</div>
</div>
</div>
<p>
<button type="submit" [disabled]="!contactForm.valid">Submit</button>
</p>
</form>
</div>
<div style="float: right; width:50%;">
<h3>Form Status</h3>
<b>valid : </b>{{contactForm.valid}}
<b>invalid : </b>{{contactForm.invalid}}
<b>touched : </b>{{contactForm.touched}}
<b>untouched : </b>{{contactForm.untouched}}
<b>pristine : </b>{{contactForm.pristine}}
<b>dirty : </b>{{contactForm.dirty}}
<b>disabled : </b>{{contactForm.disabled}}
<b>enabled : </b>{{contactForm.enabled}}
<h3>Form Value</h3>
{{contactForm.value |json}}
</div>
FormBuilder API makes it easier to work with the reactive forms in Angular. We can make use of the group, array & control methods to build ourFormModel. FormBuilder reduces the code required to write the complex forms.