Angular Custom Validation

Angular Custom Validation

Angular Custom Validation


Angular is a powerful front-end framework that allows developers to build dynamic and interactive web applications. One of the key features of Angular is its form handling capabilities. Angular provides a set of built-in validators to perform common form validations such as required fields, email format, and min/max length. However, there are cases where you need to implement custom validation logic to meet your application’s specific requirements. In this article, we will explore how to create custom validators in Angular with examples.


Why Custom Validators?

Custom validators in Angular are essential when you encounter validation scenarios that cannot be achieved using the built-in validators. Some common use cases for custom validators include:


  1. Password Confirmation: You might want to ensure that two password input fields match each other.
  2. Unique Username: Checking if a chosen username is unique in your application’s database.
  3. Conditional Validation: Implementing complex validation rules based on the state of other form controls.


Creating a Custom Validator

To create a custom validator in Angular, you need to define a function that performs the validation logic and returns a validation error object if the validation fails. This function should adhere to the signature of ValidatorFn or AsyncValidatorFn based on whether your validation logic is synchronous or asynchronous.


Synchronous Custom Validator

Here’s an example of a synchronous custom validator that checks if a name contains only letters:


import { AbstractControl } from "@angular/forms";

export default function LetterValidator(control: AbstractControl): { [key: string]: any } | null {
  if(!control.value) return null;
  
  const reg = new RegExp("^[a-zA-Z]+$");
  return reg.test(control.value) ? null : { invalidSymbols: true };
}


In this example, we define a letterValidatorfunction that returns a validator function. The validator function takes a form control as an argument and checks if it contains only letters. If not, it returns a validation error object with a invalidSymbols property.


Usage:

import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import LetterValidator from '../letters.validator';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.scss']
})
export class UserComponent {
  submitForm!: FormGroup;

  constructor(private fb: FormBuilder ) {

    this.submitForm = this.fb.group({
      name: ['', [LetterValidator]], // add validator here
    });

  }
}


Now if form control has invalid symbols we will see error message


<form [formGroup]="submitForm">
  <div>
    <mat-form-field>
      <mat-label>Name</mat-label>
      <input matInput type="text" placeholder="Name" formControlName="name" />
      
      <mat-error *ngIf="submitForm.controls['name'].hasError('invalidSymbols')">
        Only letters are allowed
      </mat-error>
      
    </mat-form-field>
  </div>
</form>


Interaction with other form controls

Now, let’s assume our validator depends on the value of another form control. A good example is the password confirmation input


So we need to create a custom validation to confirm that two password fields match each other. First, let’s create the custom validator function for password confirmation:


import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function passwordConfirmationValidator(controlName: string, matchingControlName: string): ValidatorFn {
  return (formGroup: AbstractControl): ValidationErrors | null => {
    const passwordControl = formGroup.get(controlName);
    const confirmPasswordControl = formGroup.get(matchingControlName);

    if (!passwordControl || !confirmPasswordControl) {
      return null;
    }

    if (passwordControl.value !== confirmPasswordControl.value) {
      confirmPasswordControl.setErrors({ passwordMismatch: true });
    } else {
      confirmPasswordControl.setErrors(null);
    }

    return null;
  };
}


In this code, we define a passwordConfirmationValidator function that takes two control names as arguments: controlName for the password field and matchingControlName for the confirmation password field. This function returns a validator function that compares the values of these two fields and sets a passwordMismatch error if they do not match.

Now, let’s use this custom validator in an Angular component:


import { passwordConfirmationValidator } from '../confirm-password.validator';

@Component({
  selector: 'app-register',
  templateUrl: './register.component.html'
})
export class UserComponent {
  registrationForm!: FormGroup;

  constructor(private fb: FormBuilder) {

    this.registrationForm = this.fb.group({
      password: ['', [Validators.required, Validators.minLength(3)]],
      confirmPassword: ['', [Validators.required]],
    }, {
      validator: passwordConfirmationValidator('password', 'confirmPassword')
    });

  }

}


In this component, we import and use the passwordConfirmationValidator function to create a custom validation rule for the password confirmation. We apply this custom validator to the form group by passing the control names ('password' and 'confirmPassword') to the passwordConfirmationValidator function within the validator option.

Lastly, you can display an error message in your template when the passwords don’t match:


<form [formGroup]="registrationForm">

  <div>
    <mat-form-field>
      <mat-label>Password</mat-label>
      <input matInput formControlName="password" type="password" />
    </mat-form-field>
  </div>

  <mat-form-field>
    <mat-label>Confirm Password</mat-label>
    <input matInput formControlName="confirmPassword" type="password" />
    <mat-error *ngIf="registrationForm.controls['confirmPassword'].hasError('passwordMismatch')">
      Passwords do not match.
    </mat-error>
  </mat-form-field>
  <p>
    <button type="submit" [disabled]="registrationForm.invalid">Register</button>
  </p>

</form>
</div>


Conclusion

Custom validators are a powerful tool in Angular for handling complex form validation requirements. By creating custom validators, you can tailor your validation logic to the specific needs of your application. Whether you need to perform synchronous or asynchronous validation, Angular provides a flexible framework to implement and use custom validators effectively. So, don’t hesitate to leverage custom validators to enhance the user experience in your Angular applications.


Thank you for reading until the end. Please consider following the writer and this publication. Visit Stackademic to find out more about how we are democratizing free programming education around the world.


Share Article:
  • Facebook
  • Instagram
  • LinkedIn
  • Twitter
  • Recent Posts