user8237421
user8237421

Reputation:

Why does my AsyncValidator always return true?

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

Answers (1)

Christian Vincenzo Traina
Christian Vincenzo Traina

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

Related Questions