Reactive Forms in Angular

How to build forms and manage validation easy in Angular


Reactive forms

Reactive forms are great, but they may be a bit more complex to set up. However, once everything is done, it’s very easy to work. It also makes validation much simpler, as it allows for custom validation as well as changing validation dynamically.

Import ReactiveFormsModule

To get started, you need to import the ReactiveFormsModule to your AppModule.

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { ReactiveFormsModule } from "@angular/forms"; // import it
import { HttpModule } from "@angular/http";

import { AppComponent } from "./app.component";

@NgModule({
    // ...
    imports: [
        BrowserModule,
        ReactiveFormsModule, // add it to imports
        HttpModule
    ]
    // ...
})
export class AppModule {}

Creating the form data with FormBuilder

We need to declare each form input we want with the FormBuilder. At the declaring stage, we can add both the initial value of the input, as well as which validators we want.

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

@Component({
  // ...
})
export class AppComponent implements OnInit {
  myForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
  this.myForm = this.formBuilder.group({
    name: ['ValueAtStart', Validators.required],
    email: ['', [Validators.required, Validators.email]],
    message: ['', [Validators.required, Validators.minLength(15)]]
  });
  }
}

We create a FormGroup in the MyForm. Using FormBuilder, we add three input parameters.

The name input has a modified value (ValueAtStart), which will be present at the start within the form.

The validators are also declared, you can read more about them here.

Adding to the HTML

We need to connect the form to HTML. This is done using [formGroup].

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
    <input formControlName="name" placeholder="Your name" />
    <input formControlName="email" placeholder="Your email" />
    <input formControlName="message" placeholder="Your message" />

    <button type="submit">Send</button>
</form>

Each input element is connected to the formBuilder we created earlier. To make the next part, error messages, easier, I’ll add a getter.

//...
get f() {
    return this.myForm.controls;
}

This way, we can access the form writing f[formElement] (or f.formsElement) instead of this.myForm.controls[formElement] all the time, which makes it easier to read.

Adding validation

Adding visualized error feedback to the user is easy using our new f getter.

<!-- ...  -->

<input formControlName="name" placeholder="Your name" />

<div *ngIf="f.name.errors" class="invalid-feedback">
    <div *ngIf="f.name.errors.required">
        Username is required
    </div>
</div>

<!-- ...  -->