Angular: Accessing Class Variables within Custom Validators
Aug 31, 2017 · Comments AngularReactiveFormsAngular’s built-in validators are great (Required, MinLength, MaxLength, etc.), but you’ll often find yourself needing to test unique UI control use cases. Enter custom validators, a powerful way to accomplish this:
validUsernames: AllowedUsername[];
constructor(private fb: FormBuilder,
private apiService: ApiService) { }
ngOnInit() {
this.form = this.fb.group({
// Attach a custom validator to the userName control
"userName": [this.userName, this.usernameValidator]
}
);
}
private usernameValidator(c: AbstractControl): { [key: string]: boolean } {
// check a property of c, the Control this validator is attached to
if (c.value === "bad value") {
// if a bad username is detected, return an error
return { 'badValueFound': true };
}
}
return null;
}
This works just fine if you only need to test using the properties of the AbstractControl - how about testing for valid usernames via a local array object or by making an HTTP API call?
private usernameValidator(c: AbstractControl): { [key: string]: boolean } {
// check a property of c, the Control this validator is attached to
if (this.validUsernames.contains("bad value")
|| this.apiService.isValidUsername("bad value")) {
// if a bad username is detected, return an error
return { 'badValueFound': true };
}
}
return null;
}
We get errors, though: both validUsernames and apiService will be undefined. Bummer!
Fortunately, there is a way to access them, not mentioned by the official docs. You must explicitly bind the current class to the validator function:
this.form = this.fb.group({
"userName": [this.userName, this.usernameValidator.bind(this)]
}
);
That’s all it takes. Enjoy!