Reputation:
Why does this always return the error?
export class UserExistsValidatorService implements AsyncValidator {
constructor(private userService: UserService) { }
validate(control: FormControl): Observable<ValidationErrors | null> {
return this.userService.existsUser(control.value)
.pipe(map(exists => (exists === false) ? null : {
userExists: { valid: false }
}),
catchError(() => of(null)));
}
}
This implementation of validating calls a service method which returns an Observable<boolean>
existsUser(username: string): Observable<boolean> {
return this.http.post<any>(`${environment.apiUrl}/existsUser`, { username })
.pipe(map(response => response.userExists === '1'))
.pipe(catchError(this.errorHandler));
}
I have verified the service works correctly by subscribing & logging it for a quick test:
this.userService.existsUser(this.registerGrp.controls.username.value)
.subscribe(exists => { console.log(exists); });
this prints true/false as I expect it.
However, my FormGroup.invalid always returns false. It seems that the validator always fires.
ngOnInit(): void {
// Formularmodell bauen
this.registerGrp = this.formBuilder.group({
username: ['', this.userExistsValidator],
password: [''],
// Confirm-Feld müsste eigentlich nicht auf required geprüft werden
// confirmPassword: [''],
confirmPassword: [''],
xboxName: [''],
discordName: [''],
accepted: [false]
});
}
console.log(this.registerGrp.invalid); // always false
Any ideas?
Upvotes: 1
Views: 763
Reputation: 10384
Angular isn't unwrapping your observable, it's just evaluating the whole Observable
object, which is always truthy.
The reason why it happens is that you aren't telling Angular that that is an async validator. The control
signature is able to accept up to 3 parameters: the state, the sync validators list, the async validators list.
In your case, if you don't have sync validators, you can pass null
as the second parameter:
username: ['', null, this.userExistsValidator],
Upvotes: 1