首页 > 解决方案 > 如何在 Angular 中使用自定义验证器和服务

问题描述

我尝试使用自定义验证器来检查电子邮件是否已被使用。根据文档和一些文章,我想出了这段代码:

在我的 auth.service.ts

checkEmail(email) {
    const r$ = of(true);
    const x$ = of(false);
    return this.http.post<any>(`${config.apiUrl}/users/email`, email)
    .pipe(
      mergeMap(v =>
        iif(
          () => v,
          r$,
          x$
        )
      )
    );
  }

在我的组件中

  ngOnInit() {
    this.registerForm = this.formBuilder.group({
      email: ['', [
        Validators.required,
        Validators.email,
        this.checkEmail.bind(this)
      ]]
    });
  }



checkEmail(control: AbstractControl) {
    if (control.value) {
      return this.authService.checkEmail({email: control.value}).toPromise()
      .then(response => {
        return response ? { forbiddenName: {value: control.value}} : null;
        });
    }
  }

但它不起作用,我怎样才能让 checkEmail() 函数为验证器返回正确的数据

标签: angulartypescriptvalidation

解决方案


你需要以下模组:

  ngOnInit() {
    this.registerForm = this.formBuilder.group({
      email: ['', [
        Validators.required,
        Validators.email
      ], [this.checkEmail.bind(this)]] // async validators go separate after sync validators
    });
  }



  checkEmail(control: AbstractControl) {
    if (control.value) {
      return this.authService.checkEmail({email: control.value}).pipe(
        map(response => {
          return response ? { forbiddenName: {value: control.value}} : null;
         }) // use observables, don't convert to promises
       );
    }
    return of(null); // gotta return an observable for async
  }

不需要,但这也可以更简单/更清洁:

  checkEmail(email) {
    return this.http.post<any>(`${config.apiUrl}/users/email`, email)
    .pipe(
      map(v => !!v) // map and coerce to bool
    );
  }

推荐阅读