如何在组件中使用自定义验证访问表单?

时间:2018-11-30 23:38:56

标签: angular typescript

我创建了一个自定义验证程序,以在保存新用户之前检查数据库中是否存在电子邮件,但它似乎不起作用。

我的模板

<form class="forms-sample" #f="ngForm" (ngSubmit)="onSaveUser(f.value)">
  <input type="email" class="form-control" id="email" ngModel name="email" required pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" #email="ngModel" placeholder="Email" emailValidator>
  <div *ngIf="email?.errors.emailValidator">This email has been taken, please use another one.</div>
  .......................................................
  <button class="btn btn-md-12 btn-outline-primary btn-fw btn-icon-text clickable" [disabled]="f.invalid || userFile==null" type="submit">
</form>

我的验证人

import { NG_VALIDATORS, FormControl, ValidatorFn, Validator } from '@angular/forms';
import { Directive } from '@angular/core';
import {UsersService} from '../../services/users.service';

@Directive({
  selector: '[emailValidator][ngModel]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: EmailValidator,
      multi: true
    }
  ]
})
export class EmailValidator implements Validator {

  validator: ValidatorFn;

  constructor(public usersService:UsersService) {
    this.validator = this.emailValidator("");
  }

  validate(c: FormControl) {
    return this.validator(c);
  }

  emailValidator(email:string): ValidatorFn {
    return (c: FormControl) => {
      this.usersService.checkEmailTaken(email)
        .subscribe((res)=>{
          let isValid = res;
          if (isValid==null) {
            return true;
          }
        });
      return {
        emailValidator: {
          valid: false
        }
      };
    }
  }

}

我的服务返回用户(如果存在),否则返回null。

checkEmailTaken(email: string) {
    if(this.jwtToken==null) this.authenticationService.loadToken();
    return this.http.get(this.host+"/checkEmailTaken?email="+email
      , {headers:new HttpHeaders({'Authorization':this.jwtToken})}
    );
}

该服务运行良好,但是我不知道为什么自定义验证似乎不起作用?

1 个答案:

答案 0 :(得分:0)

服务

getUserByEmail(email:string){
    if(this.jwtToken==null) this.jwtToken = this.authenticationService.loadToken();
    return this.http.get(this.host+"/userByEmail?email="+email
      , {headers:new HttpHeaders({'Authorization':this.jwtToken})}
    );
}

验证器

import { Directive } from '@angular/core';
import { AsyncValidator, AbstractControl, ValidationErrors, NG_ASYNC_VALIDATORS, AsyncValidatorFn } from '@angular/forms';
import { map } from 'rxjs/operators';
import {UsersService} from '../../services/users.service';


export function uniqueUserEmailValidator(usersService: UsersService): AsyncValidatorFn {
  return (c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
    return usersService.getUserByEmail(c.value)
      .map(data=> {
        return data ? { 'uniqueUserEmail': true } : null;
      });
  };
}

@Directive({
  selector : '[uniqueUserEmail][ngModel]',
  providers : [{ provide: NG_ASYNC_VALIDATORS, useExisting:UniqueUserEmailValidator, multi:true}]
})
export class UniqueUserEmailValidator implements AsyncValidator {

  constructor(private usersService: UsersService) {}

  validate(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
    return uniqueUserEmailValidator(this.usersService)(c);
  }
}

app.module.ts 我们必须在声明中添加验证器,以便可以在表单中使用它。

@NgModule({
  declarations: [UniqueUserEmailValidator]
})

模板

<input type="email" class="form-control" id="email" ngModel name="email" required uniqueUserEmail pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$" #email="ngModel" placeholder="Email">
<div *ngIf="email?.errors.uniqueUserEmail">This email has been taken, please use a different one.</div>