Angular, Reactive form (FormControl, FormGroup, Validators)


Simple example of Reactive forms. Everything what you need will be generated after executing this commands ng new hello-word to create new app and ng g c person-detail to create new component. After that, what you have to do, is adjust few files. Of course more you can find in Angular documentation, here we have only my notes. One more thing, if you don’t like to install node mess on your local computer you can use my or similar docker image https://hub.docker.com/r/szalek/angular-cli/

From Angular Guide: Angular reactive forms facilitate a reactive style of programming that favors explicit management of the data flowing between a non-UI data model (typically retrieved from a server) and a UI-oriented form model that retains the states and values of the HTML controls on screen. Reactive forms offer the ease of using reactive patterns, testing, and validation.

With reactive forms, you create a tree of Angular form control objects in the component class and bind them to native form control elements in the component template

What we want to buid

Angular Documentation

https://angular.io/guide/reactive-forms
https://angular.io/guide/form-validation

New app and component

By this two simple commants you will be able to create skeleton for you app. If you don’t have already angular ci, you can use my docker image https://hub.docker.com/r/szalek/angular-cli/

ng new hello-world
ng g c person-detail

Bootstrap installation

You don’t need but it will be good to install bootstrap, everything is described here
http://blog.michalszalkowski.com/java-script/angular-cli-add-bootstrap/

Requred dependencies. FormsModule

You have to extend app.module.ts by adding ReactiveFormsModule (one new import and one new item in imports section)

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import { PersonDetailComponent } from './person-detail/person-detail.component';


@NgModule({
  declarations: [
    AppComponent,
    PersonDetailComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

person-detail.component.ts

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

@Component({
  selector: 'app-person-detail',
  templateUrl: './person-detail.component.html',
  styleUrls: ['./person-detail.component.css']
})
export class PersonDetailComponent {

  personForm = new FormGroup({

    name: new FormControl('', [
      Validators.required,
      Validators.minLength(5)
    ]),
    email: new FormControl('email@email'),

    address: new FormGroup({
      city: new FormControl('Toruń'),
      street: new FormControl('Kopernika'),
      houseNumber: new FormControl('1473'),
    })

  });

  get name() {
    return this.personForm.get('name');
  }

}

person-detail.component.html

<h2>Person Detail</h2>

<form [formGroup]="personForm" novalidate class="well">

  <div class="form-group">
    <label class="center-block">Name:
      <input class="form-control" formControlName="name">
    </label>

    <div *ngIf="name.invalid && (name.dirty || name.touched)" class="alert alert-danger">
      <div *ngIf="name.errors.required">Name is required.</div>
      <div *ngIf="name.errors.minlength">Name must be at least 4 characters long.</div>
    </div>

  </div>

  <div class="form-group">
    <label class="center-block">Email:
      <input class="form-control" formControlName="email">
    </label>
  </div>

  <section formGroupName="address" class="well">
    <div class="form-group">
      <label class="center-block">City:
        <input class="form-control" formControlName="city">
      </label>
    </div>
    <div class="form-group">
      <label class="center-block">Street:
        <input class="form-control" formControlName="street">
      </label>
    </div>
    <div class="form-group">
      <label class="center-block">House Number:
        <input class="form-control" formControlName="houseNumber">
      </label>
    </div>
  </section>

</form>

<p>Form value: {{ personForm.value | json }}</p>
<p>Form status: {{ personForm.status | json }}</p>

Add new component to screen (app.component.html)

<div class="container">
  <app-person-detail></app-person-detail>
</div>

Run test server

ng serve --watch true --poll 100 --host 0.0.0.0 --port 4200 -o