Sitemap
Krishnakumar

Krishnakumar

MERN Developer with 6+ yrs in React, Node.js, MongoDB & TypeScript. Expert in full-stack apps, API integration, UI/UX, and performance optimization.

Angular Reactive Forms

4 min readFeb 22, 2024

--

Press enter or click to view image in full size

Understanding Reactive Forms:

Reactive forms in Angular are used to manage the state of form inputs in a reactive way. They are built around observable streams which represent the value and validation state of form controls. Reactive forms offer more flexibility and scalability compared to template-driven forms, especially in complex scenarios.

Key concepts in Reactive Forms:

  1. FormGroup: Represents a group of form controls. It aggregates the values of each control into a single object.
  2. FormControl: Represents a single input field — a form control instance manages the value, validation status, and user interactions of an input field.
  3. FormBuilder: A service that provides convenient methods for creating instances of FormGroup and FormControl.
  4. Validators: Functions used for synchronous and asynchronous validation of form controls.
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
selector: 'app-reactive-form',
template: `
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<label for="name">Name:</label>
<input type="text" id="name" formControlName="name">

<label for="email">Email:</label>
<input type="email" id="email" formControlName="email">

<button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>
`
})
export class ReactiveFormComponent {
myForm: FormGroup;

constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
}

onSubmit() {
if (this.myForm.valid) {
console.log('Form submitted:', this.myForm.value);
}
}
}

In this example, we create a reactive form with two form controls — ‘name’ and ‘email’. We use the FormBuilder service to create an instance of FormGroup, and define validators for each control. The form is bound to the template using formGroup directive, and formControlName is used to bind each input field to the corresponding form control. The submit button is disabled if the form is invalid, and the onSubmit method is called when the form is submitted, which logs the form values if the form is valid.

Template Driven Forms Vs. Reactive Forms:

Template-driven forms and reactive forms are two ways to create forms in Angular, each with its own strengths and weaknesses.

Get Krishnakumar’s stories in your inbox

Join Medium for free to get updates from this writer.

Template Driven Forms:

  • Easier to use and understand, especially for simple forms.
  • Form logic is mostly in the template, making it less maintainable for complex forms.
  • Two-way data binding is used [(ngModel)] for form controls.
  • Less control over form validation and error handling compared to reactive forms.

Reactive Forms:

  • More flexible and maintainable, especially for complex forms.
  • Form logic is in the component class, making it easier to test and manage.
  • Reactive forms provide better support for dynamic forms and custom validation.
  • More boilerplate code compared to template-driven forms.

In general, if you have a simple form with basic validation requirements, template-driven forms might be a good choice. However, for more complex forms with dynamic fields or advanced validation needs, reactive forms are usually the preferred approach.

Reactive Form Control and Sync View:

In reactive forms, FormControl is used to manage the value and validation state of an individual form control. It provides methods to set and get the value, update the validation status, and listen to value changes.

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

@Component({
selector: 'app-reactive-form-control',
template: `
<input type="text" [formControl]="nameControl">
<p>Value: {{ nameControl.value }}</p>
<p>Validation status: {{ nameControl.status }}</p>
`
})
export class ReactiveFormControlComponent {
nameControl = new FormControl('');

constructor() {
this.nameControl.valueChanges.subscribe(value => {
console.log('Value changed:', value);
});
}
}

In this example, we create a FormControl instance for an input field. The form control is bound to the input field using the formControl directive. We also subscribe to the valueChanges observable to listen to changes in the form control’s value and log the new value to the console.

Dynamic Validations in Reactive Forms:

In reactive forms, you can dynamically set and update validations for form controls based on user interactions or other factors. This can be done using the setValidators method of a FormControl instance.

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

@Component({
selector: 'app-dynamic-validations',
template: `
<form [formGroup]="myForm">
<input type="text" formControlName="name">
<div *ngIf="myForm.get('name').errors?.required">Name is required</div>
<button (click)="toggleValidation()">Toggle Validation</button>
</form>
`
})
export class DynamicValidationsComponent {
myForm: FormGroup;

constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
name: ['', Validators.required]
});
}

toggleValidation() {
const control = this.myForm.get('name');
if (control.validator === Validators.required) {
control.clearValidators();
} else {
control.setValidators(Validators.required);
}
control.updateValueAndValidity();
}
}

In this example, we create a form with a single form control ‘name’ that is initially required. The toggleValidation method is used to dynamically add or remove the required validation based on the current validation state of the control.

Getting Reactive Form Values:

You can get the current value of a FormGroup or FormControl by accessing the value property. This property returns an object containing the current value of each form control in the group.

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

@Component({
selector: 'app-get-values',
template: `
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<input type="text" formControlName="name">
<input type="email" formControlName="email">
<button type="submit">Submit</button>
</form>
`
})
export class GetValuesComponent {
myForm: FormGroup;

constructor(private fb: FormBuilder) {
this.myForm = this.fb.group({
name: [''],
email: ['']
});
}

onSubmit() {
console.log('Form values:', this.myForm.value);
}
}

In this example, we create a form with two form controls ‘name’ and ‘email’. The onSubmit method logs the current values of the form controls when the form is submitted.

--

--

Krishnakumar
Krishnakumar

MERN Developer with 6+ yrs in React, Node.js, MongoDB & TypeScript. Expert in full-stack apps, API integration, UI/UX, and performance optimization.