A custom validator function enforces an application-specific policy that built-in Angular validators do not provide. Its factory accepts configuration and returns a function that examines an AbstractControl, producing ValidationErrors when the value is invalid or null when it passes. section 22.3
Use the validator at the level that owns the data being checked:
- Attach a control validator to validate one field, such as limiting a Price value to a configured maximum. section 22.3
- Create a directive when applying custom validation to a template-driven form; register it through NG_VALIDATORS so Angular invokes it. section 22.3.1
- Attach validation to a FormGroup or FormArray when a policy depends on multiple related fields. section 22.3.2
Limiting a price
LimitValidator.Limit(300) returns a validator that parses the control value and reports a limit error when the value is not numeric or exceeds 300. The error can carry both the configured limit and actual value, allowing a validation helper to display a tailored message. Applying the validator alongside Angular's built-in validators makes an over-limit Price field visibly invalid. section 22.3
Detecting duplicate keywords
A UniqueValidator applied to a FormArray checks its controls for repeated nonempty values. Editing the Kayak product so that the second keyword becomes boat produces a validation error. Cross-field validation may require additional handling when the error belongs to the array but the interface colors individual controls; manual updates use updateValueAndValidity, and the demonstrated improvement relies on deferred updates to avoid an infinite loop. section 22.3.2
Listing 22.12. The contents of the limit.ts file in the src/app/validation folder
import { AbstractControl, ValidationErrors, ValidatorFn }
from "@angular/forms";
export class LimitValidator {
static Limit(limit:number) : ValidatorFn {
return (control: AbstractControl) : ValidationErrors | null => {
let val = parseFloat(control.value);
if (isNaN(val) || val > limit) {
return {"limit": {"limit": limit, "actualValue": val}};
}
return null;
}
}
}
Inspect the complete LimitValidator implementation, including its factory signature, control inspection, structured error, and null success result. section 22.3
