In my Angular 4 app, I have a custom form validator that looks like this:
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';
export function myCustomValidator(myCustomArg: string): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (control.value) {
// do some checks with control.value and myCustomArg
// return error if needed
}
// return null otherwise
control.setErrors(null);
return null;
};
}
but when I try to use it in one of my reactive forms:
ngOnInit() {
this.form = new FormGroup({
'myControl': new FormControl(null, [ myCustomValidator(...) ]),
// ...
});
}
I get several errors:
ERROR TypeError: Cannot read property 'emit' of undefined at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl._updateControlsErrors (forms.es5.js:2836) at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl.setErrors (forms.es5.js:2772) at file-extension.validator.ts:17 at forms.es5.js:506 at Array.map () at _executeValidators (forms.es5.js:506) at FormControl.validator (forms.es5.js:462) at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl._runValidator (forms.es5.js:2720) at FormControl.webpackJsonp.../../../forms/@angular/forms.es5.js.AbstractControl.updateValueAndValidity (forms.es5.js:2688) at new FormControl (forms.es5.js:3011)
ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 0, nodeDef: {…}, elDef: {…}, elView: {…}}
ERROR Error: formGroup expects a FormGroup instance. Please pass one in.
But unfortunately they are not very helpful.
The issue is related with the way the validator is assigned to the field.
In fact, the validator is trying to access to the control's value control.value
.
But when the validator factory function is called, the control doesn't exist yet:
this.form = new FormGroup({
'myControl': new FormControl(null, [ myCustomValidator(...) ]),
// ...
});
So in order to solve the issue, just create the form first and then assign the validator:
ngOnInit() {
// first create the form with its controls
this.form = new FormGroup({
'myControl': new FormControl(null),
// ...
});
// then assign the custom validator
this.form.get('myControl').setValidators([
myCustomValidator(...),
]);
}