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.
Table of Contents
What is FormBuilder
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.
How to use FormBuilder
Import & inject FormBuilder API
To use the FormBuilder
, first, we need to import
it in our component
1 2 3 | import { FormBuilder } from '@angular/forms' |
Next, we need to inject it into our component class
1 2 3 4 | constructor(private formBuilder: FormBuilder) { } |
Finally, use the group
, array
& control
methods to build the FormModel
FormGroup
We use the group
method to build the Form Group. We pass the list of Form Controls, Form Array, or another Form Group to 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.
1 2 3 4 5 6 7 8 9 10 | this.contactForm = this.formBuilder.group({ firstname: [''], lastname: [''], email: [''], gender: [''], isMarried: [''], country: [''], }); |
Nested FormGroup
Creating a Nested FormGroup is just as easy. use the formbuilder.group
method, as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | this.contactForm = this.formBuilder.group({ firstname: [''], lastname: [''], email: [''], gender: [''], isMarried: [''], country: [''], address: this.formBuilder.group({ city: [''], street: [''], pincode: [''] }) }) |
Validations
The second argument to the FormControl is the list of sync validators. The following example shows how to add validators.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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]], }) }); |
FormBuilder Example
We learned how to build reactive forms the Angular Reactive forms tutorial.
app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 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; } } |
app.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | <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> |
References
Summary
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.
- Angular Forms Tutorial: Fundamental & Concepts
- Template Driven Forms in Angular
- Set Value in Template Driven forms in Angular
- Reactive Forms in Angular
- FormBuilder in Reactive Forms
- SetValue & PatchValue in Angular
- StatusChanges in Angular Forms
- ValueChanges in Angular Forms
- FormControl
- FormGroup
- FormArray Example
- Build Dynamic or Nested Forms using FormArray
- Validations in Reactive Forms in Angular
- Custom Validator in Reactive Forms
- Passing Parameter to Custom Validator in Reactive Forms
- Inject Service into Custom Validator
- Validation in Template Driven Forms
- Custom Validator in Template Driven Forms
I understand, FormBuilder and Reactive forms make testing and control over inputs easier, but still the code looks way smaller and efficient while using template driven forms. Also if working with many input fields, Reactive Forms does not follow the “Separation of Concerns” Principle because component is controlling the entire template. Other than Unit Testing and Better control, Is there any more advantage of using Reactive forms over template driven forms ?
good
Requires ReactiveFormsModule to be added to the Module !!
what is ng form and its work
what is ng form and its work
but you didnt show the html of the form…
The code of app.component.html is under FormBuilder Example section