Angular 自定义验证器。如何使用给定的 Promise 验证表单字段?

Angular Custom Validators. How to validate a form field using a given Promise?

我需要使用 returns Promise 的方法来验证表单字段。但它永远不会 returns 错误,因为 Promises 是异步的。

这是我的验证器:

static email(usersService: UsersService): ValidatorFn {

  return (control: AbstractControl):{ [key: string]: boolean | null } => {
    const email = control.value;
    if (email) {
      usersService.validateUsername(email).then(
        (result) => { return result.username ? {emailExists: true} : null }
      )
    } else {
      return null;
    }
  }}

这是我的 UsersService 方法

validateUsername(username: string): Promise<{"username": string}> {
  return this.httpClient.post('/users/username_validation', {"username": username}).pipe(
    map((body: {"username": string}) => body),
  ).toPromise()}

我认为你错过了 return 的承诺,这应该有效

if (email) {
  return usersService.validateUsername(email).then( // here in this line
    (result) => { return result.username ? {emailExists: true} : null }
  )
}

您可以将其重构为

 return (control: AbstractControl):Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => 
 {
  const email = control.value;
  return (email &&  usersService.validateUsername(email).then( 
    (result) => { return result.username ? {emailExists: true} : null }
  )) || null;
 }

我需要做的就是像这样使用 AsyncValidator:

validator.ts

import { Injectable } from '@angular/core';
import { AbstractControl, AsyncValidator, ValidationErrors } from '@angular/forms';
import { Observable} from 'rxjs';

import { UsersService } from "@app/users/users.service";


@Injectable({
  providedIn: 'root'
})

export class EmailValidator implements AsyncValidator {

  constructor( private usersService: UsersService ) { }

  validate( control: AbstractControl): Promise<ValidationErrors> | Observable<ValidationErrors> {

    const email = control.value;
    if (email) {
      return this.usersService.validateUsername(email).then(
        (result) => { 
          console.log(result)
          return result.username ? {emailExists: true} : null 
        }
      )
    } else {
      return null;
    }

  }
}