NashTech Insights

Reactive Form Custom Validation Arrays in Angular

Alka Vats
Alka Vats
Table of Contents

Angular provides a powerful and flexible way to handle form validations using Reactive Forms. While Angular offers built-in validators, there are often cases where you need to implement custom validations, especially when dealing with complex data structures like arrays. In this blog, we will explore how to perform custom validations on arrays within Reactive Forms in Angular, with detailed examples.

If you want to learn one more feature of angular, you can refer here.

Prerequisites

Before diving into custom validation arrays, make sure you have a basic understanding of Angular and Reactive Forms. If not, consider checking the official Angular documentation for a comprehensive introduction.

Setting up the Angular Project

So, If you haven’t already set up an Angular project, you can do so by running the following commands:

ng new custom-validation-array-example
cd custom-validation-array-example
ng generate component my-form

Creating a Reactive Form

Inside the my-form component, let’s create a reactive form that includes an array control. In this example, we’ll create a form to collect a list of email addresses.

// my-form.component.ts

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

@Component({
  selector: 'app-my-form',
  templateUrl: './my-form.component.html',
  styleUrls: ['./my-form.component.css']
})
export class MyFormComponent {
  myForm: FormGroup;

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

  // Custom validator for email array
  validateEmailArray(control: FormArray): { [key: string]: any } | null {
    const emails = control.value;
    if (emails.some(email => !Validators.email(email))) {
      return { invalidEmail: true };
    }
    return null;
  }

  get emailArray() {
    return this.myForm.get('emailArray') as FormArray;
  }

  addEmail() {
    this.emailArray.push(this.fb.control('', [Validators.required, Validators.email]));
  }

  removeEmail(index: number) {
    this.emailArray.removeAt(index);
  }

  submitForm() {
    if (this.myForm.valid) {
      // Handle form submission
      console.log(this.myForm.value);
    } else {
      // Form is invalid
    }
  }
}

n this code, we create a form group with a form array named emailArray. We use a custom validator validateEmailArray to ensure that all email addresses in the array are valid. The addEmail and removeEmail methods allow users to add and remove email inputs dynamically. Finally, the submitForm method handles the form submission.

Building the Template

Now, let’s build the form template in my-form.component.html:

<!-- my-form.component.html -->

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
  <div formArrayName="emailArray">
    <div *ngFor="let email of emailArray.controls; let i = index">
      <div class="form-group">
        <label for="email{{ i }}">Email {{ i + 1 }}</label>
        <input type="email" class="form-control" [formControlName]="i" id="email{{ i }}">
        <button type="button" (click)="removeEmail(i)">Remove</button>
      </div>
    </div>
  </div>
  <button type="button" (click)="addEmail()">Add Email</button>
  <button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>

This template displays the form array of email inputs and provides buttons to add and remove email addresses. The form submission button is disabled when the form is invalid.

Styling (Optional)

You can add some CSS to style your form to make it more user-friendly. Here’s an example of CSS to style the form:

/* my-form.component.css */

.form-group {
  margin-bottom: 10px;
}

button {
  margin-top: 10px;
}

Understanding Reactive Forms and Custom Validation

Reactive Forms in Angular are a powerful way to manage and validate forms. These forms are built using FormGroup, FormControl, and FormArray classes from the @angular/forms module. While Angular provides built-in validators like Validators.required, Validators.email, and more, there are times when you need to implement custom validation logic, especially when dealing with complex data structures like arrays.

What is a FormArray?

A FormArray is a class in Angular that represents an array of form controls. It’s used to handle dynamic lists of data within a form. Each item in the array corresponds to a form control, which can have its own validation rules.

In the previous example, we created a form with a FormArray named emailArray to collect a list of email addresses. Here’s how we did it:

this.myForm = this.fb.group({
  emailArray: this.fb.array([], [Validators.required, this.validateEmailArray])
});
  • this.fb.array([]) initializes an empty FormArray.
  • [Validators.required, this.validateEmailArray] specifies validators for the entire FormArray.

Implementing Custom Array Validation

Therefore, to implement custom validation for a FormArray, we define a custom validator function. In our example, we used validateEmailArray:

// Custom validator for email array
validateEmailArray(control: FormArray): { [key: string]: any } | null {
  const emails = control.value;
  if (emails.some(email => !Validators.email(email))) {
    return { invalidEmail: true };
  }
  return null;
}

In this validator function:

  • We access the value of the FormArray using control.value.
  • We use the Array.prototype.some() method to check if any of the email addresses are invalid based on the Validators.email validator.
  • If any email is invalid, we return a validation error object with the key invalidEmail, indicating that the FormArray is invalid. Otherwise, we return null.

Displaying Validation Errors

Hence, to display validation errors in the template, you can use Angular’s formGroup, formArrayName, and formControlName directives:

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
  <div formArrayName="emailArray">
    <div *ngFor="let email of emailArray.controls; let i = index">
      <div class="form-group">
        <label for="email{{ i }}">Email {{ i + 1 }}</label>
        <input type="email" class="form-control" [formControlName]="i" id="email{{ i }}">
        <button type="button" (click)="removeEmail(i)">Remove</button>
        <div *ngIf="email.invalid && email.touched">
          <div *ngIf="email.hasError('required')">Email is required.</div>
          <div *ngIf="email.hasError('email')">Invalid email format.</div>
        </div>
      </div>
    </div>
  </div>
  <button type="button" (click)="addEmail()">Add Email</button>
  <button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>

In this template:

  • We use formArrayName="emailArray" to bind the FormArray.
  • Inside the *ngFor loop, we use [formControlName]="i" to bind each control.
  • We display validation errors using *ngIf directives and Angular’s error checking methods like email.hasError('required').

Dynamic Adding and Removing of Controls

Our form allows users to dynamically add and remove email input fields. Here’s how it’s done:

addEmail() {
  this.emailArray.push(this.fb.control('', [Validators.required, Validators.email]));
}

removeEmail(index: number) {
  this.emailArray.removeAt(index);
}
  • addEmail() pushes a new FormControl into the FormArray when the “Add Email” button is clicked.
  • removeEmail(index: number) removes a control at the specified index when the “Remove” button is clicked.

Handling Form Submission

Finally, when the form is submitted, we check its validity before processing the data:

submitForm() {
  if (this.myForm.valid) {
    // Handle form submission
    console.log(this.myForm.value);
  } else {
    // Form is invalid
  }
}

We ensure that the form is valid before proceeding with form submission logic.

Conclusion

Angular Reactive Forms provide a robust mechanism for handling and validating forms, including forms with complex data structures like arrays. By creating custom validators and using the FormArray class, you can implement custom array validations tailored to your application’s specific requirements. This tutorial has demonstrated how to create a form to collect a list of email addresses and implement custom validation for the email array. You can apply similar principles to other scenarios that involve dynamic arrays and custom validation logic in your Angular applications.

Finally, for more such posts, please follow our LinkedIn page- FrontEnd Competency.

Alka Vats

Alka Vats

Alka Vats is a Software Consultant at Nashtech. She is passionate about web development. She is recognized as a good team player, a dedicated and responsible professional, and a technology enthusiast. She is a quick learner & curious to learn new technologies. Her hobbies include reading books, watching movies, and traveling.

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

%d bloggers like this: