问题
I'm trying to create a custom async validator for my registration form where it checks if an email already exists. The backend returns 404 if the email does not exist and 200 if it does exist (can't change this old code).
I have found a couple tutorials but didn't find one using the latest rxjs library. I created this Validation class:
export class UniqueEmailValidator {
static createValidator(httpClient: HttpClient, degree: number, wlId: number) {
return (control: AbstractControl) => {
return httpClient.get(`${url}?degree=${degree}&email=${control.value}&wl_id=${wlId}`)
.pipe(
map(
(response: Response) => {
return response.status === 404 ? null : { emailNotUnique: true };
}
)
);
};
}
}
and in my ts file creating the form I'm using this
this.registerForm = this.fb.group({
email: ['', [Validators.required, Validators.email], UniqueEmailValidator.createValidator(
this.httpClient, this.wlService.wl.degree, this.wlService.wl.id)],
The xhr call is being done and returned correctly but the form control of email is staying as pending. Any ideas on what I did wrong?
回答1:
Figured it out after a while and more research.
Validation class:
@Injectable()
export class UniqueEmailValidator {
constructor(private http: HttpClient) {}
searchEmail(email: string, degree: number, wlId: number) {
return timer(1000)
.pipe(
switchMap(() => {
// Check if email is unique
return this.http.get<any>(`${url}?degree=${degree}&email=${email}&wl_id=${wlId}`);
})
);
}
createValidator(degree: number, wlId: number): AsyncValidatorFn {
return (control: AbstractControl): Observable<{ [key: string]: any } | null> => {
return this.searchEmail(control.value, degree, wlId)
.pipe(
map(
(response: Response) => {
return null;
},
),
catchError(
(err: any) => {
return err.status === 404 ? of(null) : of({ emailNotUnique: true });
},
),
);
};
}
}
Not sure if timer can be changed but I found it in an article and it works fine. Would love some confirmation on that.
Basically I'm doing a catchError since the response from the backend returns 404 and returning an observable again from the catchError.
Then in the form creation I'm doing:
this.registerForm = this.fb.group({
email: ['', [Validators.required, Validators.email], this.uniqueEmailValidator.createValidator(
this.wlService.wl.degree, this.wlService.wl.id
)],
And I added the UniqueEmailValidator as a provider in the module and injected in this component constructor.
来源:https://stackoverflow.com/questions/55279113/angular-7-custom-async-validator