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 validatorexport 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