Reputation: 1677
I'm doing a web application in Angular 10 with a simple form to receive two values that I will be validating them on the backend, doing a HTTP call. To accomplish this I have created an async validator which runs perfectly.
Problem: It's not setting the error to the FormGroup. In other words, the FormGroup is always valid.
this.form = this.fb.group({
// I will validate this two values with the backend
patientIdentifications: this.fb.group({
clinicRecord: [null, Validators.required],
documentId: [null, Validators.required]
}, {
updateOn: 'blur',
asyncValidators: CustomValidators.isPatientValid(this.myService) // <= async validator
}),
// Just to illustrate that I have more FormControls
firstName: [null, Validators.required],
});
Async validator
export class CustomValidators {
static isPatientValid(myService: MyService): AsyncValidatorFn {
return (formGroup: FormGroup):
Promise<ValidationErrors | null> |
Observable<ValidationErrors | null> => {
const clinicRecordControl = formGroup.controls.clinicRecord;
const documentIdControl = formGroup.controls.documentId;
const clinicRecordValue = clinicRecordControl.value;
const documentIdValue = documentIdControl.value;
return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
map(patient => patient ? of(null) : of({valid: true})),
catchError(() => of(null))
);
};
}
}
The HTTP call is done perfectly when the two inputs loses the focus. But the error is not being set in the FormGroup.
I have tried these solutions:
#1. Adding bind()
to the validator call
patientIdentifications: this.fb.group({
clinicRecord: [null, Validators.required],
documentId: [null, Validators.required]
}, {
updateOn: 'blur',
asyncValidators: CustomValidators.isPatientValid(this.myService).bind(this) // <= bind
}),
#2. Remove the of
function
return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
map(patient => patient ? null : {valid: true}), // <= remove the "of"
catchError(() => of(null))
);
#3. Setting the error directly using the FormGroup's instance
return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
map(patient => patient ? formGroup.setErrors(null) : formGroup.setErrors({valid: true})),
catchError(() => of(null))
);
None of the solutions have worked for me.
My goal is to set the error to the FormGroup correctly to have the FormGroup as INVALID
, which is the correct thing to do.
Upvotes: 1
Views: 2551
Reputation: 28338
Right now you're saying that errors are OK since you're not returning of({valid: true})
but rather of(null)
. If you change it to this instead it will work:
return myService.getPatient(clinicRecordValue, documentIdValue).pipe(
map(patient => patient ? of(null) : of({valid: true})),
catchError(() => of({valid: true))
);
};
Based on your comment which asks whether to return an observable or use formGroup.setErrors(null)
I would go with an observable as it seems to be the recommended way when looking at the docs for custom validators. This is irregardless of when you're using async or synchronous validators.
Upvotes: 1