How to get the max value from FormControl’s validator

Unfortunately `hasValidator` does not work well with validators created dynamically like `Validator.max` but there is a solution that allows getting information about max value anyway.

You can view the source code for this project by following this link: GitHub

Demo

Problem with hasValidator

Let’s create a simple FormControl with max validator. To check if the control has some validator we can use the hasValidator method but it does not work correctly for Validators.max(18) because calling Validators.max(18) creates another reference and the implementation of hasValidator check validators by reference.

import { FormControl, Validators } from "@angular/forms";

const ageControl = new FormControl(null, [Validators.max(18)]);
passwordControl.hasValidator(Validators.max(18)); // -> false

// ---

const max18Validator = Validators.max(18);
const ageControl = new FormControl(null, [max18Validator]);
confirmPassword.hasValidator(max18Validator); // -> true

Checking if a control has a max validator without hasValidator

To check if the control has a max validator we can use knowledge about numbers. We can get all control’s validators and check if we get the max error for Infinity.

import { AbstractControl, FormControl, Validators } from "@angular/forms";

const maxAgeControl = new FormControl(null, [Validators.max(18)]);
const hasMaxValidator = hasControlMaxValidator(maxAgeControl);
console.log(hasMaxValidator); //-> true

function hasControlMaxValidator(control: AbstractControl): boolean {
  const validator = control.validator;

  if (validator === null) {
    return false;
  }

  const errors = validator(new FormControl(Infinity)) ?? {};
  return "max" in errors;
}

Because nothing can be bigger than Infinity we are sure that we cause an error if the validator contains max validator.

Getting max value from the validator

To get information about the max value from the validator first we need to cause an error. In the error details, we have information about the max value and actual value of a control.

import { AbstractControl, FormControl, Validators } from "@angular/forms";

const maxAgeControl = new FormControl(null, [Validators.max(18)]);
const maxValue = getMaxValue(maxAgeControl);
console.log(maxValue); //-> 18

function getMaxValue(control: AbstractControl, fallback: number): number;
function getMaxValue(control: AbstractControl): number | undefined;
function getMaxValue(control: AbstractControl, fallback?: number): number | undefined {
  const validator = control.validator;

  if (validator === null) {
    return fallback;
  }

  const errors = validator(new FormControl(Infinity)) ?? {};
  return "max" in errors ? errors["max"]["max"] : fallback;
}

We have to write errors['max']['max'] because first max is the error key and the second max is the value passed as the argument of Validators.max function.

const control = new FormControl(6, Validators.max(3));
console.log(control.errors); // { max: { max: 3, actual: 6 } }

Do you like the content?

Your support helps me continue my work. Please consider making a donation.

Donations are accepted through PayPal or Stripe. You do not need a account to donate. All major credit cards are accepted.

Leave a comment