Angular Reactive forms (FormsModule). Is it necessary?
Tags: angular, form, validations
Published: 2020-08-01 11:20:14

Reactive forms was introduced in angular from earlier versions itself. Its a standard now. But why do we use it. Is it really necessary?

# Introduction
Reactive forms provide us a way to create immutable forms and object driven approach of creating forms. This way we can easily declare and handle all the form validations and events at one place and reuse the code. But how?

In this article i have tried to explain as simple and easy as possible. Keeping things straight and not much on in depth basic details. If needed angular has a very good documentation where you will get a ton of details. I have provided the links too.

# Basic template driven forms

Before seeing reactive forms lets just look at how most of us do form data handling initially. If you don't want to, then skip to next section.

1. First we create a form.
2. Create new variable for each form items (Like email, name, etc...). Then assign it as ngModel for data biding in HTML.
3. On form submit / on blur of form fields, etc... We call a function that validates the form fields one by one and throws error.
Almost forgot, how do you show the error ? Yah, create a new object to store each form fields error and show in HTML.

> HTML
```
<form>
    <h1>
        Sample Login
    </h1>
    <div>
        <label>Email: </label>
        <input type="email">
        <span *ngIf="error.email">{{error.email}}</span>
    </div>
    <div>
        <label>Password: </label>
        <input type="password">
        <span *ngIf="error.password">{{error.password}}</span>
    </div>
</form>
```
> component.ts
```
  email: string;
  password: string;
  error = {
    email: null,
    password: null
  };

  formSubmit() {
    if (this.validate()) {
      /* Submit */
    }
  }

  validate(): boolean {

    /* Validate email */
    if (!this.email || this.email.length < 8) {
      this.error.email = 'Email is required and has min 8 charecters';
      return false;
    } else { this.error.email = null; }

    /* Validate password */
    if (!this.password || this.password.length < 8) {
      this.error.password = 'Password is required and has min 8 charecters';
      return false;
    } else { this.error.password = null; }

    return true;
  }

```
Done, u sure ? Nope, we gotta do the same for rest of the forms in the whole application. **OMG** This goes on... Imagine changing something in this mess. I know there are a ton of ways we can optimise this. But trust me its still not convincing enough to not use reactive forms.

These are useful for adding a simple form to an app, such as an email list, signup form. They’re easy to add to an app, but they don’t scale as much as reactive forms. If you have very basic form requirements and logic, use the template-driven forms.

# Reactive forms

At first sight Reactive forms might seem complicated but they can be very useful when you actually get it. They are really powerful and flexible.

**Well, then how does FormModule really help here?**
It lets you create form groups and form controls. Using this one can easily control the validations and value in a form. Also with just one line we can validate the complete form `form.markAllAsTouched();`. Like this there are ton of features to help us. Below is a simple sample.

**Step 1**: First We will have to import the FormsModule and ReactiveFormsModule in the app.module.ts file. Once done we can use it in the declared component(AppComponent).
> ap.module.ts
```
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ]
})
export class AppModule { }
```
**Step 2**: In the component create a **form group** object which represents a form(login form). Within this form group object each value will be **form control**. This can be represented as each form fields like email and password.
> TS (AppComponent)
```
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-profile-editor',
  templateUrl: './profile-editor.component.html',
  styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
  loginForm = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.minLength(8)]),
    password: new FormControl('', [Validators.required, Validators.minLength(8)]),
  });
}
```
**Step 3**: Add the form in html and under ngModel attribute add the corresponding form control value `[(ngModel)]="loginForm.email"`.

Now to show the error we can add a span below the input. Add a if condition to check of the user has entered details in the field and is invalid.
> HTML
```
<input id="name" type="email" class="form-control"
      required [(ngModel)]="loginForm.email" #name="ngModel" >

<span *ngIf="loginForm.email.invalid && (loginForm.email.dirty || loginForm.email.touched)"
    class="alert alert-danger">
    Email must is required and must be greater than 8 charecters
</span>
```
Below are the simple error value keys available for each form control by default.

* **valid**: This property returns true if the element’s contents are valid and false otherwise.
* **invalid**: This property returns true if the element’s contents are invalid and false otherwise.
* **pristine**: This property returns true if the element’s contents have not been changed (controls just loaded then returns true).
* **dirty**: This property returns true if the element’s contents have been changed.
* **untouched**: This property returns true if the user has not visited the element.
* **touched**: This property returns true if the user has visited the element.

# Advantages
1. Easily to maintain
2. Automated validations
3. Can perform additional features like call a function after value changes ex: `form.controls['email'].valueChanges.subscribe(<function to execute>)`
4. Can pass form values to child components easily and even get updated values and perform actions. This is a topic for another article.

# Disadvantages
1. Maybe the error handing can be improved. As we still need to write custom spans to handle errors of each input. This can be done, i have done it here [https://dev.to/vishesh/custom-error-handling-in-angular-reactive-forms-5f05](https://dev.to/vishesh/custom-error-handling-in-angular-reactive-forms-5f05).

# Conclusion

I highly recommend people to use reactive forms throughout their projects. It will save you from a lot of work. If found use full do like and share this article with your friends.

# References
1. Basic info - [https://angular.io/guide/reactive-forms](https://angular.io/guide/reactive-forms)
2. This URL will help u understand the features of form control.  [https://angular.io/api/forms/FormControl](https://angular.io/api/forms/FormControl)
3. This URL will give you a list of all clases, drirectives, etc.. Available in the reactive form. [https://angular.io/api/forms](https://angular.io/api/forms)