Angular FormControl: Complete Guide with Examples

Angular FormControl

Forms are an essential data collection mechanism in modern web development. Proper form management becomes crucial while developing web applications, no matter the development technology you’re using. Major Angular development companies leverage the Reactive Forms module to deal with dynamic form inputs. The Reactive Forms module works on a model-driven approach to create and manage forms. Reactive Forms are more flexible and scalable than template-driven forms. There are some core concepts Angular developers must understand to create effective dynamic forms using the Reactive Forms module. 

In this Angular blog, we’ll understand the Angular FormControl, its features, and working; FormGroup and its features, how to set up Reactive Forms, explaining the development of custom form control, and strongly typed FormControl.

1. What is Angular FormControl?

FormControl is the fundamental concept of Reactive Forms in Angular. Form control deals with the data and validation rules of a single input field, be it a textbox or any other form element. FormControl is an object that tracks the user interaction, value, and validation status of all the fields associated with the control. 

1.1 The Life and Times of a FormControl

A FormControl transitions through different stages based on how users interact with the form. These states give an idea about the pattern of user interaction with the form. 

  • Value: It denotes the current value of the control that is entered by the user or set by you.
  • Validation Status: It’s a boolean value that shows whether the input is valid or invalid.
  • Touched/Untouched: It helps to identify the user interaction status with the input. 
  • Dirty/Pristine: It specifies any modifications in the input value.

Syntax

import { FormControl } from '@angular/forms';
const myFormControl = new FormControl('Initial Value', [Validators]);

1.2 Features of Angular FormControl

Below are the key features of FormControl, the heart of the Reactive Forms module:

  • One FormControl object deals with tracking changes of a single form control.
  • You have the flexibility to implement both built-in and custom validation for a particular form control. 
  • You can use FormControl in association with directives such as ngModel and formControlName in template-driven or reactive forms. 
  • It supports real-time validation with the help of synchronous and asynchronous validators. 
  • The valueChanges() and statusChanges() return an Observable instance. 

2. What is a Form Group in Angular?

FormGroup, as the name indicates, is a collection of FormControls encapsulated as a single unit. This single unit represents some related sections of the form or the complete Reactive form. Every FormControl in the group is associated with a particular form control in the component code. 

2.1 FormGroup Properties and Methods

1. Properties

  • controls: An object containing the FormControl instances that belong to this group.
  • value: It is an object with key-value pairs that indicate the current value of the group.
  • valid: It is a boolean value denoting the validity of the form group’s value.
  • invalid: It is a boolean value denoting the invalidity of the form group’s value.
  • touched: A boolean indicating whether any control in the group has been touched.
  • untouched: A boolean indicating whether no control in the group has been touched.
  • pristine: A boolean indicating whether no control in the group’s value has been changed.
  • dirty: This boolean value indicates if any control in the group’s value is modified or not.
  • status: The current validation status of the group (valid, invalid, pending, or disabled).

2. Methods

  • addControl (name: string, control: AbstractControl): Adds a control to the form group.
  • removeControl (name: string): Removes a control from the form group.
  • setControl (name: string, control: AbstractControl): Replaces an existing control.
  • contains (controlName: string): Checks if a control with the given name exists in the group.
  • setValue (value: { [key: string]: any }): Sets new values for the form group.
  • patchValue (value: { [key: string]: any }): Patches the form group with new values.
  • reset (value?: any): Resets the form group with an optional value.
  • markAsTouched (opts?: { onlySelf?: boolean }): This method will mark the group and all its controls as touched.
  • markAsUntouched (opts?: { onlySelf?: boolean }): Marks the group and all its controls as untouched.
  • markAsDirty (opts?: { onlySelf?: boolean }): Marks the group and all its controls as dirty.
  • markAsPristine (opts?: { onlySelf?: boolean }): Marks the group and all its controls as pristine.

2.2 Features of Angular FormGroup

  • It brings together the related form controls, facilitating easier management.
  • It keeps a check on the value and validity of all the form controls in a group. 
  • Can be nested to build hierarchical forms.
  • FormGroup consists of various methods allowing the retrieval of form control values and programmatically resetting them.
  • Supports the implementation of control validation at both the individual and group levels.

3. FormControl and FormGroup in Angular

In Angular, FormControl is a key class used to handle the value and validation state of a single form element. It allows developers to track user input, manage validations, and respond to changes or events. Together with FormGroup and FormArray, it forms the core structure of Angular’s reactive forms. As it extends AbstractControl, FormControl inherits essential methods and properties for form handling. 

On the other hand, FormGroup acts as a container for multiple FormControl instances, grouping them under a single object using named keys. It monitors the overall value and validation status of all its child controls. If any one of the controls becomes invalid, the entire FormGroup reflects that invalid state, making it easier to manage and validate complex form structures effectively.

4. Set up Reactive Forms in Angular

Prerequisites for setting up and implementing the Reactive Forms in Angular:

  • Install Angular CLI on your system if you haven’t with the below command:
    • npm install -g @angular/cli
  • Create a new Angular project using the command
    • ng new your-project-name
  • Move into your above-created Angular project folder using:
    • cd your-project-name

Now let’s proceed to the main steps:

4.1 Import the ReactiveFormsModule

The ReactiveFormsModule is the main component here, containing all the necessary tools. Open the app.module.ts file and add the following imports:

import { ReactiveFormsModule } from '@angular/forms';
 
@NgModule({
 declarations: [
   // Your components here
 ],
 imports: [
   // Other modules here
   ReactiveFormsModule // Add this line
 ],
 providers: [],
 bootstrap: [AppComponent]
})
export class AppModule { }

4.2 Create the Form Model

We’ll create our form model in the app.component.ts file. You can imagine this model as the blueprint for our contact form.

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
 
 
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 // Create a new FormControl with an initial value of an empty string.
 name = new FormControl('');
}

4.3 Designing the Template

Now, let’s sketch the form in our app.component.html. This is where our FormControl comes to life in the user interface.

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

The [formControl] directive binds our name FormControl in the component class to the input element in the template.

4.4 Save and Sync Data

To see the values immediately as the user types, we’ll now add some code below our input to see the form control’s value in real-time.

<div>
 <label for="name">Name:</label>
 <input id="name" type="text" [formControl]="name">
</div>
<div>
 <p>Your name is: {{ name.value }}</p>
</div>

When a form grows to include more fields, like adding an ’email’ input, FormGroup becomes especially useful. Think of it as assembling a puzzle, where each FormControl is a piece, and FormGroup helps organize those pieces into a complete picture. FormGroup binds all the related controls together, making the form easier to manage, validate, and scale.

4.5 Create a FormGroup

In the app.component.ts, we’ll refactor our code to include a FormGroup:

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
 
 
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 // We're creating a FormGroup which is a group of FormControls.
 contactForm = new FormGroup({
   name: new FormControl(''), // Our existing name FormControl
   email: new FormControl('') // A new FormControl for the email
 });
}

4.6 Update the Template with FormGroup

Modify app.component.html to use the FormGroup. Here’s how to connect the dots:

<form [formGroup]="contactForm">
 <div>
   <label for="name">Name:</label>
   <input id="name" type="text" formControlName="name">
 </div>
 <div>
   <label for="email">Email:</label>
   <input id="email" type="email" formControlName="email">
 </div>
 <button type="submit" [disabled]="!contactForm.valid">Submit</button>
</form>

Observe the implementation of formGroup to bind our template to the contactForm group and formControlName for associating each input to its respective FormControl within the group.

4.7 Refactor with FormBuilder

Inject FormBuilder into the component you’ve created and then use it to create the form group:

import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
 
 
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
})
export class AppComponent {
 contactForm: FormGroup;
 
 
 constructor(private fb: FormBuilder) {
   // Using FormBuilder to create the FormGroup.
   this.contactForm = this.fb.group({
     name: [''], // Define the default value and validators inside the array
     email: ['']
   });
 }
}

FormBuilder provides a shorthand called the fb.group() method to create the FormGroup and its internal FormControls.

4.8 Submitting the Form

At last, we’ll handle the form submission. Here, we have to include one method for managing the submit event in the app.component.ts:

submit() {
 console.log(this.contactForm.value);
}

Then, update your form in app.component.html to call the submit() method when the form is submitted:

<form [formGroup]="contactForm" (ngSubmit)="submit()">
 <!-- Form inputs stay the same -->
 <button type="submit" [disabled]="!contactForm.valid">Submit</button>
</form>

5. How Do Standard Form Controls Work?

To create a custom form control, it’s important to first grasp how Angular’s built-in form controls function. These built-in controls are designed to interact directly with standard HTML elements like input fields, text areas, checkboxes, and similar components.

The following code is to create a simple form having several plain HTML form fields:

<div [formGroup]="form">
 
    <input placeholder="Course title" formControlName="title">
 
    <input type="checkbox" placeholder="Free course" formControlName="free">
 
    <textarea placeholder="Description" formControlName="longDescription">
 
    </textarea>
 
</div>

6. Final Thoughts

Angular’s FormControl is a powerful tool that enables precise control over individual form elements, supporting both reactive and dynamic forms. It allows developers to track user input, apply validations, and handle value or status changes efficiently. With the introduction of strict typing support in Angular 14, FormControl becomes even more robust, reducing the likelihood of type-related errors and improving code quality. Whether building simple or complex forms, understanding and leveraging FormControl is essential for developing scalable, maintainable applications. By mastering this feature, developers can ensure seamless user experiences and create forms that are secure and flexible across various use cases.

profile-image
Parind Shah

Parind Shah is responsible for frontend innovations at TatvaSoft. He brings profound domain experience and a strategic mindset to deliver exceptional user experience. He is always looking to gain and expand his skill set.

Comments

Leave a message...