Gentle Introduction to Reactive Forms in Angular
Tags: javascript, angularforms, reactiveforms
Published: 2017-12-18 11:13:28

---
title: Gentle Introduction to Reactive Forms in Angular
published: true
description: introduction to reactive forms, angular
tags: javascript, angular forms, reactive forms
---

Reactive forms are forms where we write logic, validations, controls in the components class part of the code unlike the template driven forms where control is done in the template. The reactive form is flexible and can be use to handle any complex form scenarios. We write more component code and less html code which make unit testing easier.

### Enabling Reactive&nbsp;Forms

To use reactive form, we need to explicitly import `{FormsModule, ReactiveFormsModule}`in our application module from `@angular/forms`

```
import { ReactiveFormsModule } from '@angular/forms';
@Component({...})
export class App { }
@NgModule({ 
	declarations: [App], 
    imports: [BrowserModule, ReactiveFormsModule], 
    bootstrap: [App]
})
export class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
```

### FormControl and FormGroup

You need to understand `FormControl` and `FormGroup` to be able to create forms in angular, hence we will talk about the `FormControl` and `FormGroup` below.

The `FormControl` is a class that powers an individual form control, tracks the value and validation status, whilst offering a wide set of public API methods. Below is a basic example of a `FormControl`

```
'firstname': new FormControl('');
```

The `FormGroup` is a group of FormControl instances, keeps track of the value and validation status for the said group, and also offers public APIs. Below is a basic example of the`FormGroup`

```
this.myGroup = new FormGroup({ 
	'firstname': new FormControl(''), 
    'password': new FormControl('')
});
```

The above has shown us how to create an instance of `FormControl` and a `FormGroup`, we can use them within our template like below:

```
<form [formGroup]="myGroup"> 
	Firstname: <input type="text" formControlName="firstname"> 
    Password: <input type="password" formControlName="password">
</form>
```

Notice the `<form [formGroup]="myGroup">`, the `formGroup` must be equal to the name used to initialise the `FormGroup` within the component which is `myGroup`. The `formControlName` must also be equal to the name used to initialise the `FormControl` in the component class. Below is the code structure in app.component.ts.

```
//app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from "@angular/forms";

@Component({ 
	selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit { 
	title = 'reactive forms'; myGroup: FormGroup;
	constructor() {}

	ngOnInit() { 
    	this.myGroup = new FormGroup({ 
        	'firstname': new FormControl(''), 
            'password': new FormControl('') }); 
        }
    }
```

The template code below

```
<form [formGroup]="myGroup"> 
	<div class="form-group"> 
    	<label for="firstname" class="label-control">Firstname:</label> 
        <input type="text" formControlName="firstname" class="form-control"> 		</div>

	<div class="form-group">
    	<label for="password" class="label-control">Password:</label> 
        <input type="password" formControlName="password" class="form-control"> 	</div>
</form>
```

### Nested FormGroups

At times, when building a complex form. Need might arise were we need make a particular value a parent to some other inputs, so we can access those inputs under the parent. In the example below, `account` will be a parent to `firstname` and `password` which means we will be able to access firstname and password under account.

```
@Component({...})
export class SignupFormComponent { 
	form = new FormGroup({ 
    	'email': new FormControl(''), 
        'account': new FormGroup({ 
        	'firstname': new FromControl(''), 
            'password': new FromControl(''), 
        })
    });
}
```

We can represent the nested form group within our template like below

```
<form [formGroup]="form"> 
	<div formGroupName="account">
		<div class="form-group"> 
        	<label for="firstname">Firstname: </label> 
            <input formControlName="firstname" id="firstname" 
            	type="text" class="form-control" > 
        </div>

		<div class="form-group"> 
        	<label for="password">Password: </label> 
            <input formControlName="password" id="password" 
            		type="password" class="form-control" > 
        </div>
	</div>
</form>
```

Notice `formGroupName` is equal to `account` which is the name assigned to the FormGroup instance within our component. The `formGroupName` act as a parent to the firstname and password form control.

### Simplify with FormBuilder

Instead of using `FormGroup` and `FormControl` directly, we can use a magical API that does it all for us. So there will be no need to import `FormGroup` and `FormControl`, all we just need import is the `FormBuilder`

```
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from "@angular/forms";

@Component({ 
	selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit { 
	title = 'reactive forms'; 
    myGroup: FormGroup;

	constructor(private formBuilder: FormBuilder) {}

	ngOnInit() { 
    	this.myGroup = this.formBuilder.group({ 
        	'firstname': this.formBuilder.control(''), 
            'password': this.formBuilder.control('') 
        }); 
    }
}
```

### Reactive Submit

To get the data when the user submit the form, we are going to apply the `(ngSubmit)="handleSubmit()"` to the `<form>`which will link to a method in our component to handle the submitted data

```
<form [formGroup]="myGroup" (ngSubmit)="handleSubmit()">
	<div class="form-group"> 
		<label for="firstname" class="label-control">Firstname:</label 
        <input type="text" formControlName="firstname" class="form-control"> 		</div>

	<div class="form-group"> 
    	<label for="password" class="label-control">Password:</label> 
        <input type="password" formControlName="password" class="form-control"> 	</div>

	<button class="btn btn-primary">submit</button>
</form>
```

We can access the form data within our component like below:

```
handleSubmit() { 
	console.log(this.form.value); 
}
```

### Adding Validation

To add validation to a reactive form, we need to import the `Validators` class from `@angular/forms` and pass the `validation(s)`in as a second argument to our `FormControl` instances.

```
import { FormBuilder, Validators } from '@angular/form';
@Component({...})
export class SignupFormComponent implement OnInit {

	constructor(private formBuilder: FormBuilder) {}

	ngOnInit() { 
    	this.myGroup = this.formBuilder.group({ 
        	'firstname': this.formBuilder.control('', Validators.required), 				'password': this.formBuilder.control('', Validators.required) 
        }); 
    }

}
```

When we need to use more than one validator, we make the second parameter an array like below:

```
'firstname': ['', [Validators.required, Validators.minLength(2)]]
```

### Displaying Validation Error

We can add validation error message to our template by listening to the `errors` object in the `FormControl`. Thanks to typescript getter, which I use to make the template cleaner

```
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from "@angular/forms";

@Component({ 
	selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit { 
	title = 'reactive forms'; 
    myGroup: FormGroup;

	constructor(private formBuilder: FormBuilder) {} 
    ngOnInit() { 
    	this.myGroup = this.formBuilder.group({ 
        	'firstname': this.formBuilder.control('',Validators.required), 					'password': this.formBuilder.control('', Validators.required) 
        }); 
    }

	get firstname() { 
    	return this.myGroup.get('firstname'); //notice this 
    }

	get password() { 
    	return this.myGroup.get('password'); //and this too 
    }
}
```

We can display validation errors like below within our template

```
<form [formGroup]="myGroup" (ngSubmit)="handleSubmit()"> 
	<div class="form-group"> 
    	<label for="firstname" class="label-control">Firstname:</label> 
        <input type="text" formControlName="firstname" class="form-control" >

		<div *ngIf="firstname.invalid && firstname.touched"> 
        	<div *ngIf="firstname.errors.required"> Firstname is required </div> 		 </div> 
    </div>

	<div class="form-group"> 
    	<label for="password" class="label-control">Password:</label> 
        <input type="password" formControlName="password" class="form-control" >

		<div *ngIf="password.invalid && password.touched"> 
        	<div *ngIf="password.errors.required"> Password is required </div> 			</div> 
    </div>

	<button class="btn btn-primary">submit</button>
</form>
```

### Disable Submit&nbsp;Button

we can disable the submit button when the form is not valid by hooking to the form group valid status like below, note that `myGroup` is the form control.

```
<button class="btn btn-primary" [disabled]="! myGroup.valid"> submit</button>
```

There is more to reactive forms like custom validation and asynchronous validation, there are many articles out there to help with them.

_I am happy to share this article with you&nbsp;. If you’ve enjoyed this article, do show support by giving a few claps_ 👏_&nbsp;. Thanks for your time and make sure to follow me or drop your comment below_ 👇