Reputation: 1769
Within my FormGroup there is a FormArray that will contain n number of FormControls, each of these FormControls has an email validator attached to it.
I want my FormArray to be able to know whether or not any of the FormControls have an email validation error, and if so the FormError errors property should be set to {email: true}
.
To do this, I have written a custom validator that is applied to my FormArray. However this validator does not seem to be firing properly when FormControl elements are added or removed from the FormArray.
this.form = this.formBuilder.group({
alertContacts: this.formBuilder.array(this.alertData.alertContacts, [Validators.required, alertContactsArrayValidator]),
});
This form array is controlled by a child component that has a referenece to the formArray passed to it as an input upon instantiation. The method in the child component to add a value to the formArray is
pushToFormcontrol(value: any) {
if(!this.fArray.value.includes(value)){
if(this.usesAutocomplete){
if(this.autocompleteData.some(el => el === value)) {
this.fArray.push(this.formBuilder.control(value));
this.filterAutocomplete();
this.clearInput();
}
} else {
this.fArray.push(this.formBuilder.control(value, [Validators.email]));
this.clearInput();
}
}
this.fArray.markAsDirty();
}
The custom validator for my FormArray is
export function alertContactsArrayValidator(): ValidatorFn {
return (formArray: FormArray): { [key: string]: any } | null => {
console.log(formArray);
let hasEmailErrors = false;
let formControls = formArray.controls;
console.log(formControls);
formControls.forEach(control => {
let controlErrors: ValidationErrors = control.errors;
console.log("Current control errors: ", controlErrors);
Object.keys(controlErrors).forEach(key => {
if (key === 'email') {
hasEmailErrors = true;
console.log("key has email");
}
});
});
return hasEmailErrors ? {email: true} : null;
};
}
If I debug my code in the browser I can see that the outer alertContactsArrayValidator function is stepped into but the returned inner function is never activated. I never see any of the console logs either.
EDIT
After some further experimentation I've found something interesting. If I modify my FormArray so that I'm inserting an empty array instead of my this.alertData.alertContacts
which is an array of strings, the validator works perfectly. I'm starting to think this is an issue with the way I'm creating the FormArray.
this.form = this.formBuilder.group({
alertContacts: this.formBuilder.array([], [Validators.required, alertContactsArrayValidator]), //An empty array works fine
});
If I want to instantiate my FormArray with elements already inside of it, should I be doing it in a different way than just passing the array as the first parameter of the this.formBuilder.array()
method?
Upvotes: 1
Views: 3012
Reputation: 6414
Unlike Validator
, ValidatorFn
should be fired manually (Angular doesn't call it itself to let you pass in some useful configurations) as below:
this.form = this.formBuilder.group({
alertContacts: this.formBuilder.array(
this.alertData.alertContacts,
[Validators.required, alertContactsArrayValidator()]
),
});
Edit:
this.form = this.formBuilder.group({
alertContacts: this.formBuilder.array(
this.alertData.alertContacts.map(x => new FormControl(x, [
Validators.required,
alertContactsArrayValidator()
])),
),
});
Upvotes: 2