12/16/2018 - 10:45 AM

[Angular reactive forms] #angular

[Angular reactive forms] #angular

Reactive Forms

A quick reference guide on how to setup.

How to setup

import ReactiveFormsModule

import { ReactiveFormsModule } from '@angular/forms';
@NgModule ({
  imports: [

define a FormGroup

import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';

export FormComponent {

  public userForm: FormGroup;
    private fb: FormBuilder
    this.userForm = this.fb.group({
      username: ['user1', Validators.required]    //default value = 'user1', Optional validator = required
    this.username = this.userForm.controls['username'];   //optional. Allows easier reference in HTML template
  public onSubmit(formValue: any) {
    console.log('You submitted: ', formValue);


Create form and bind controls

<form [formGroup]="userForm"

  <label for="usernameElm">Username</label>
  <input type="text"
    placeholder="enter username here"
    optionally you could bing the element to the Control property:

  <button type="submit">Submit</button>


Handling errors and validation

Checking whole form validity example

  <button [disabled]="!userForm.valid"

Detecting errors in controls

  <input [class.error]="!userForm.controls['username'].valid"

Handling specific validation errors

  <div *ngIf="userForm.controls['username'].hasError('required')">
    You must enter a username

Good practice: see if control is touched

  <!-- we are using the reference variable for leaner code -->
  <input [class.error]="!username.valid && username.touched"
  <div *ngIf="username.hasError('required') && username.touched"

Other validation options

Errors from FormGroup level

You can check for errors of specific field even in FormGroup level:

  console.log (userForm.hasError('required','username');  // FormGroup.hasError(errorKey, fieldKey)

Custom Validators

Create a function that accepts FormControl object as parameter and returns an error string map {errorKey: boolean} if the error is valid.

Define Validator Example: Not allow 'admin' as username.

private reservedUsernames (control: FormControl): { [string]: boolean } {
  if (control.value === 'admin') {
    return {reserved: true};

Apply Validator

this.userForm = this.fb.group({
  username: ['', Validators.compose(
    [Validators.required, this.reservedUsernames]

Check in HTML template

<div *ngIf="userForm.controls['username'].hasError('reserved')">
  Username reserved and cannot be used.

Monitor changes

There is an available Observable valueChanges in both FormGroup and FormControl classes.

  (value: any) => console.log('Form Value changed to', value)

  (value: string) => console.log('Current username: ', value);

2-way data bind

If you need to... you can bind an input control value to an external variable.

Component class:

public currentUsername: string;

//example of setting the value of currentUsername
  public suggest() {
    this.currentUsername = 'user'+Math.floor((Math.random() * 10) + 1);

HTML template:

  <!-- ngModel binds the input element value to variable
  <input type="text"
    placeholder="enter username here"
  <!-- the currentUsername reflects the value of input element -->
  <div> Current Value: {{currentUser}}</div>
  <!-- setting the currentUsername reflects the value back to input element -->
  <button (click)="suggest()">Suggest a username</button>

Note: ngModel binds the input element value to variable. We still have to use [formControl] to bind the input element with the rest of our FormGroup and make it part of it (validation, etc).


  • When Angular sees [formGroup] in a <form> element, it does not automatically bind the ngForm FormGroup.