Reactive Forms

Angular: The Full Gamut Edition

Charlie Greenman
April 22, 2021
10 min read

Reactive forms are underrated.

As previously just discussed, there are many reasons as to why forms are very complicated. Reactive forms are no exception to that rule.

Registering Reactive Forms

Importing a reactive module, is no different than your regular module, however,this is the module to use to when importing reactive forms.

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [// other imports ...
    ReactiveFormsModule
  ],})export class AppModule { }

Generating a component, and adding FormControl

No different than any other scenario:

ng generate component grid-form

In your component simply add a new FormControl:

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

@Component({
  selector: 'px-grid-form',
  templateUrl: './grid-form.component.html',
  styleUrls: ['./grid-form.component.css']})export class NameEditorComponent {
  size = new FormControl('');}

Registering Control in Template

<label>
  Name:
  <input type="text" [formControl]="name"></label>

As mentioned in the previous chapter, FormControl, will allow you to access value of form within component, and view. Most importantly, update in view or component, and have it affect the other.

Displaying Component

We can now include the component in any other component. E.g.

<px-grid-form></px-grid-form>

Grouping Form Controls

A FormControl on it's own has value. Primarily being able set a value, andaccesing it within the template. However, a formControl is incomplete without a formGroup. A formGroup, will give us access to all of the formControl values, so we can use them all, when submitting a form.

import { Component } from '@angular/core';import { FormGroup, FormControl } from '@angular/forms';
 
@Component({
  selector: 'px-grid-form',
  templateUrl: './grid-form.component.html',
  styleUrls: ['./grid-form.component.css']})export class GridFormComponent {
  gridForm = new FormGroup({
    row: new FormControl(''),
    column: new FormControl(''),});}

Connecting FromGroup model and view

<form [formGroup]="gridForm"><label>
    First Name:
    <input type="text" formControlName="row"></label><label>
    Last Name:
    <input type="text" formControlName="column"></label></form>

Within our template, we attach theformGroup directive supplied bythe ReactiveFormsModule, to our component's new FormGroup.

Saving Form Data

The formGroup directive internally has an (ngSubmit) method, that can be used to call whenever you are ready to save data for the entire form, and pass it along to the backend.

<form [formGroup]="gridForm" (ngSubmit)="onSubmit()">
onSubmit() {// this is where data for gridForm is exposedconsole.log(this.gridForm.Value);}

Nested Form Groups

In Angular, there is the ability to create nested form groups:

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

@Component({
  selector: 'px-code-form',
  templateUrl: './code-form.component.html',
  styleUrls: ['./code-form.component.css']})export class CodeFormComponent {
  profileForm = new FormGroup({
    row: new FormControl(''),
    column: new FormControl(''),
    address: new FormGroup({
      street: new FormControl(''),
      city: new FormControl(''),
      state: new FormControl(''),
      zip: new FormControl('')})});}

A great way to think of nested form groups, is that it is exactly like creating a nested data object. The only different is that any parent, contains formGroup, whereas children use formControl.

Grouping nested form in the template

Now that we have created a nested FormGroup property within a class, lets' goahead and show how we would access these values within our template.

<div formGroupName="address"><h3>Address</h3><label>
    Street:
    <input type="text" formControlName="street"></label><label>
    City:
    <input type="text" formControlName="city"></label><label>
    State:
    <input type="text" formControlName="state"></label><label>
    Zip Code:
    <input type="text" formControlName="zip"></label></div>

We are using the formGroupNamedirective. The formGroupName directive, will sync a formGroup to a template. That allows us to access any children ofthat formGroup by simply accessing name, using formControlName.

Partial Model Updates

We have already discussed in the previous chapter, the ability to update a specific formControl by using thesetValue() option is definitely a viable option. However, what if we would like to update multiple values at the same time within a formGroup() Angular provides the method called patchValue(). So for instance, let's say we wantedto update the firstName, and street address:

updateProfile() {this.profileForm.patchValue({
    firstName: 'Nancy',
    address: {
      street: '123 Drew Street'}});}

Generating form controls with FormBuilder

The Angular team realized how excessive it is to constantly include FormControl'sand FormGroup's everytime one wants to build out a form. Insteadthey created something called the FormBuilder.

import { Component } from '@angular/core';import { FormBuilder } from '@angular/forms';
  
  @Component({
    selector: 'app-profile-editor',
    templateUrl: './profile-editor.component.html',
    styleUrls: ['./profile-editor.component.css']})export class ProfileEditorComponent {
    profileForm = this.fb.group({
      firstName: [''],
      lastName: [''],
      address: this.fb.group({
        street: [''],
        city: [''],
        state: [''],
        zip: ['']}),});constructor(private fb: FormBuilder) { }}

As we can see in the above, instead of having to attach FormGroup to theparents, and attaching FormControl to every child, we can just use fb.group on every parent.

Subscribe to the Razroo Angular Newsletter!

Razroo takes pride in it's Angular newsletter, and we really pour heart and soul into it. Pass along your e-mail to recieve it in the mail. Our commitment, is to keep you up to date with the latest in Angular, so you don't have to.

More articles similar to this