DEV Community

Cover image for Simplifying Form Management in Angular with FormGroupDirective
Amin-Karimi
Amin-Karimi

Posted on

Simplifying Form Management in Angular with FormGroupDirective

As an Angular developer, managing forms can sometimes be a daunting task, especially when using ngValueAccessor. While ngValueAccessor is powerful, it often requires implementing numerous functions to handle value retrieval and updates for our form elements. Recently, I transitioned to using FormGroupDirective, and it has significantly streamlined the process. Here’s why this switch was a game-changer for me and my team:

Why FormGroupDirective?

  1. Simplicity in Implementation
    With FormGroupDirective, much of the boilerplate code required by ngValueAccessor is eliminated. This means less time writing repetitive code and more time focusing on business logic.

  2. Better Synchronization of Values
    FormGroupDirective automatically synchronizes values, so there’s no need to write additional functions for value retrieval and setting. This makes the code cleaner and easier to maintain.

  3. Improved Code Readability
    Code written with FormGroupDirective is significantly more readable and understandable. This is especially beneficial for the entire development team, including newcomers.

  4. Greater Flexibility
    Using FormGroupDirective provides more flexibility in managing forms, allowing us to easily handle more complex forms.

Let's dive into a practical example to illustrate how FormGroupDirective can simplify form management.

Before: Using ngValueAccessor

import { Component, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

@Component({
  selector: 'app-custom-input',
  template: `
    <input type="text" [value]="value" (input)="onInput($event.target.value)" />
  `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true,
    },
  ],
})
export class CustomInputComponent implements ControlValueAccessor {
  value: string;

  onChange: any = () => {};
  onTouched: any = () => {};

  writeValue(value: any): void {
    this.value = value;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  onInput(value: string) {
    this.value = value;
    this.onChange(value);
  }
}
Enter fullscreen mode Exit fullscreen mode

After: Using FormGroupDirective

import { Component, Input } from '@angular/core';
import { FormGroup, FormGroupDirective, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-custom-form',
  template: `
    <form [formGroup]="form">
      <input [formControlName]="controlName" />
    </form>
  `,
  standalone:true,
  imports:[ReactiveFormsModule]
})
export class CustomFormComponent {
  form!: FormGroup;
  @Input({ required: true }) controlName!: string

  constructor(private _rootFormGroup: FormGroupDirective,) {
    this.form = this._rootFormGroup.control as FormGroup;
  }

}
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
jangelodev profile image
João Angelo

Hi Amin-Karimi,
Top, very nice and helpful !
Thanks for sharing.

Collapse
 
aminkarimi_sis profile image
Amin-Karimi

Hi João Angelo,
Thank you! I'm glad you found it helpful.