How to display max length based on FormControl’s validator

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

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

Demo

Take a look at the title hint. Try to provide a title longer than 15 chars.

Problem with hasValidator

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

import { FormControl, Validators } from "@angular/forms";
const titleControl = new FormControl(null, [Validators.maxLength(15)]);
titleControl.hasValidator(Validators.maxLength(15)); // -> false
// ---
const max15Chars = Validators.maxLength(15);
const titleControl = new FormControl(null, [max15Chars]);
titleControl.hasValidator(max15Chars); // -> true

Checking if a control has a maxLength validator without hasValidator

To check if the control has a maxLength validator let’s first take a look into maxLength implementation.

// The fragment of maxLength validator
export function maxLengthValidator(maxLength: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
return hasValidLength(control.value) && control.value.length > maxLength
? { maxlength: { requiredLength: maxLength, actualLength: control.value.length } }
: null;
};
}
// ---
function hasValidLength(value: any): boolean {
return value != null && typeof value.length === "number";
}

As you can see validator checks if a control’s value has a valid length (if it is an object with a length property) and then compares this length with maxLength argument.

We can use this knowledge to create a fake object with a length property. We can get all control’s validators and check if we get the maxLength error for { length: Infinity }.

import { AbstractControl, FormControl, Validators } from "@angular/forms";
function hasMaxLengthValidator(control: AbstractControl): boolean {
const validator = control.validator;
if (validator === null) {
return false;
}
const errors = validator(new FormControl({ length: Infinity })) ?? {};
return "maxlength" in errors;
}
const titleControl = new FormControl(null, [Validators.maxLength(15)]);
const hasMaxLengthValidator = hasMaxLengthValidator(titleControl);
console.log(hasMaxLengthValidator); //-> true

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

Getting maxLength value from the validator

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

import { AbstractControl, FormControl, Validators } from "@angular/forms";
function getMaxLengthFromValidator(control: AbstractControl, fallback: number): number;
function getMaxLengthFromValidator(control: AbstractControl): number | undefined;
function getMaxLengthFromValidator(control: AbstractControl, fallback?: number): number | undefined {
const validatorFn = control.validator;
if (validatorFn === null) {
return fallback;
}
const errors = validatorFn(new FormControl({ length: Infinity }));
return errors?.["maxlength"]["requiredLength"] ?? fallback;
}
const titleControl = new FormControl(null, [Validators.max(15)]);
const maxLengthValue = getMaxLengthFromValidator(titleControl);
console.log(maxLengthValue); //-> 15

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.

Portrait of the author

About me

On a daily basis, I work as a Front-End Developer with a primary focus on JavaScript. I feel most comfortable with Angular and NestJS, but I’m always eager to venture beyond a single tech stack. I effectively leverage AI tools in my workflow, which allows me to quickly onboard into new technologies and write code in other languages or frameworks whenever needed.

After hours, I bring my passion for tech into the physical world. I run my own homelab, where I experiment with server management and build home automation and monitoring powered by Home Assistant.

Leave a comment