Nwose Lotanna Web Developer and Writer

FormGroup and FormControl in Angular

5 min read 1459

How To Manage Reactive Form Controls With Form Groups In Angular 8

When working with JavaScript frameworks, it’s best to avoid using clustered templates because the form logic lies in the component class. Reactive forms in Angular allow you to create clean forms without using too many directives. They also reduce the need for end-to-end testing since it’s very easy to validate your forms.

Put simply, form controls in Angular give the developer all the control, and nothing is implicit anymore — every choice about inputs and controls must be made intentionally and, of course, explicitly.

In this tutorial, we’ll show you how to divide form controls by form groups to create clusters that provide a platform to easily access the template element as groups. We’ll cover the following in detail:

To illustrate the concept of form groups in Angular, we’ll walk through the process of building a reactive form so that you can fully grasp how to set it up with form groups.

To follow along, download the starter project on GitHub and open it in VS Code. If you haven’t already, you’ll want to update to the most recent version, Angular 11.

What are form controls in Angular?

In Angular, form controls are classes that can hold both the data values and the validation information of any form element. Every form input you have in a reactive form should be bound by a form control. These are the basic units that make up reactive forms.

What is a form group in Angular?

Form groups wrap a collection of form controls. Just as the control gives you access to the state of an element, the group gives the same access but to the state of the wrapped controls. Every single form control in the form group is identified by name when initializing.

FormControl and FormGroup in Angular

FormControl is a class in Angular that tracks the value and validation status of an individual form control. One of the three essential building blocks in Angular forms — along with FormGroup and FormArrayFormControl extends the AbstractControl class, which enables it to access the value, validation status, user interactions, and events.

FormGroup is used with FormControl to track the value and validate the state of form control. In practice,  FormGroup aggregates the values of each child FormControl into a single object, using each control name as the key. It calculates its status by reducing the status values of its children so that if one control in a group is invalid, the entire group is rendered invalid.

Registering form groups in Angular

The first step is to tell Angular that you want to use the form group by importing it inside the appropriate component.

We made a custom demo for .
No really. Click here to check it out.

To see how this works, navigate to the employee.component.ts file and paste in the code block below:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms'
@Component({
  selector: 'app-employee',
  templateUrl: './employee.component.html',
  styleUrls: ['./employee.component.css']
})
export class EmployeeComponent implements OnInit {
  bioSection = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    age: new FormControl('')
  });
constructor() { }
ngOnInit() {
  }
}

Here the form group was both imported and initialized to group together some form controls that compose the bio section of the form. To reflect this group, you have to associate the model to the view with the form group name, like this:

// copy inside the employee.component.html file
<form [formGroup]="bioSection" (ngSubmit)="callingFunction()">

  <label>
    First Name:
    <input type="text" formControlName="firstName">
  </label>
<label>
    Last Name:
    <input type="text" formControlName="lastName">
  </label>
<label>
    Age:
    <input type="text" formControlName="age">
  </label>
<button type="submit">Submit Application</button>
</form>

Just like the form control, the form group name is used to identify the form group in the view, and on submit, the callingFunction will be triggered.

Your app.component.html file should look like this:

<div style="text-align:center">
  <h2>Angular Job Board </h2>
  <app-employee></app-employee>
</div>

Now run your application in development with the command:

ng serve

It should look like this:
Angular Job Board Form


Nesting form groups in Angular

The Angular reactive forms API makes it possible to nest a form group inside another form group.

Copy the code block below into the employee.component.ts file:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms'
@Component({
  selector: 'app-employee',
  templateUrl: './employee.component.html',
  styleUrls: ['./employee.component.css']
})
export class EmployeeComponent implements OnInit {
  bioSection = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    age: new FormControl(''),
    stackDetails: new FormGroup({
      stack: new FormControl(''),
      experience: new FormControl('')
    }),
    address: new FormGroup({
        country: new FormControl(''),
        city: new FormControl('')
    })
  });
constructor() { }
ngOnInit() {
  }
  callingFunction() {
    console.log(this.bioSection.value);
   }
}

The main form group wrapper is the bio section, inside which both the stack details group and the address group is nested. As you can see, nested form groups are not defined by the assignment statement, but rather with the colon, just like a form control.

Reflecting this in the view will look like this:

// copy inside the employee.component.html file
<form [formGroup]="bioSection" (ngSubmit)="callingFunction()">
    <h3>Bio Details
</h3>

  <label>
    First Name:
    <input type="text" formControlName="firstName">
  </label> <br>
<label>
    Last Name:
    <input type="text" formControlName="lastName">
  </label> <br>
<label>
    Age:
    <input type="text" formControlName="age">
  </label>
<div formGroupName="stackDetails">
    <h3>Stack Details</h3>

    <label>
      Stack:
      <input type="text" formControlName="stack">
    </label> <br>

    <label>
      Experience:
      <input type="text" formControlName="experience">
    </label>
  </div>
<div formGroupName="address">
    <h3>Address</h3>

    <label>
      Country:
      <input type="text" formControlName="country">
    </label> <br>

    <label>
      City:
      <input type="text" formControlName="city">
    </label>
  </div>
<button type="submit">Submit Application</button>
</form>

It’s crucial that every name in the model and view match, so make sure you don’t misspell the form control names. When you save and run the application, if you do get any errors, read the error message and correct the misspelling you must have used.

You can style your component with the style instructions below:

input[type=text] {
    width: 30%;
    padding: 8px 14px;
    margin: 2px;
    box-sizing: border-box;
  }
  button {
      font-size: 12px;
      margin: 2px;
      padding: 8px 14px;
  }

If you run the application, you should see something like this in your browser:
Angular Job Board Form Bio
When you use the form and submit, you will see your input results returned in the browser console. The complete code used in this tutorial is available on GitHub.

How to add a FormControl to a FormGroup

To add, update, or remove controls in FormGroup, use the following commands:

  • addControl() adds a control and updates its value and validity
  • removeControl() removes a control
  • setControl() replaces an existing control
  • contains() checks for enabled controls associated with a given name
  • registerControl() registers a control but, unlike the other methods, does not update its value and validity

How to set a FormGroup value

In Angular, you can set values to individual form groups or set all FormGroup values at once.

Use patchValue to set only some values:

this.myFormGroup.patchValue({
  formControlName1: myValue1, 
  // formControlName2: myValue2
});

You do not need to supply all values here; fields whose values were not set will be unaffected.

To set all FormGroup values simultaneously, use setValue:

this.myFormGroup.setValue({
  formControlName1: myValue1, 
  formControlName2: myValue2
});

What is FormBuilder in Angular?

Setting up form controls can be tedious, especially if you’re working with very long forms. Angular’s FormBuilder helps you streamline the process of building advanced forms while avoiding repetition.

Put simply, FormBuilder provides syntactic sugar that eases the burden of creating instances of FormControl, FormGroup, or FormArray and reduces the amount of boilerplate required to build complex forms.

For a deeper dive and examples on how to build complex forms, read our comprehensive Angular form builder tutorial.

Conclusion

In this tutorial, we covered everything you need to know about form controls in Angular, including how to use FormControl, how to group form controls with FormGroup, and why it’s critical to capture controls’ collective instances at once.

Experience your Angular apps exactly how a user does

Debugging Angular applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Angular state and actions for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens on your site including network requests, JavaScript errors, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket NgRx plugin logs Angular state and actions to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Angular apps - .

Nwose Lotanna Web Developer and Writer

One Reply to “FormGroup and FormControl in Angular”

  1. how to write error message for a control of nested form ?
    *ngIf=”parentForm.controls.controlitem.errors”

Leave a Reply