验证用户名存在异步

Validate Username Exist Async

我正在尝试通过异步验证程序判断用户名是否可用来验证用户名,我已经尝试了很多解决方案,但我不知道如何解决这个问题,我遇到了这个错误:

Error: Expected validator to return Promise or Observable.

我的方法 validateUsername() 不完整,我该如何让它工作?

register.component.ts

this.registerForm = this.fb.group({
            username: ['', [Validators.required], this.validateUsername.bind(this)],
            email: ['', [Validators.required,
                Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')]],
            password: this.fb.group({
                pwd: ['', [Validators.required, Validators.minLength(1)]], // todo
                confirmpwd: ['', [Validators.required, Validators.minLength(1)]]// todo
            }, {
                validator: this.mustMatch('pwd', 'confirmpwd'),
            }),
            birthday: ['', Validators.required]
        });
    }


validateUsername(control: AbstractControl) {
        this.userservice.checkUserExist(control.value).subscribe(
            res => {
                this.exist = 'username available ';
            },
            error => {
                this.exist = 'username unavailable ';
            }
        );
    }

register.component.html

<div class="form-group">
                <label for="inputName" class="font-weight-bold">Usuario</label>
                <div class="input-group Name">
                    <div class="input-group-prepend">
                        <div class="input-group-text"><i class="fa fa-user" aria-hidden="true"></i>
                        </div>
                    </div>
                    <input type="text" class="form-control"  id="inputName" name="inputName" formControlName="username"
                           placeholder="Identificador de usuario">
                </div>
                <div *ngIf="username.invalid && username.touched" class="col-4 p-0 ml-5 text-danger">
                    <p *ngIf="username.errors?.required">
                        Escoger un nombre de usuario
                    </p>
                    <p *ngIf="username.errors?.usertaken">
                        Este usuario ya existe
                    </p>
                </div>
            </div>

这是给你的例子

一个简单的组件初始化我们的反应形式并定义我们的异步验证器:validateEmailNotTaken。请注意我们的 FormBuilder.group 声明中的表单控件如何将异步验证器作为第三个参数。这里我们只使用一个异步验证器,但你想将多个异步验证器包装在一个数组中:

app.component.ts

import { Component, OnInit } from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  Validators,
  AbstractControl
} from '@angular/forms';

import { SignupService } from './signup.service';

@Component({ ... })
export class AppComponent implements OnInit {
  myForm: FormGroup;

  constructor(
    private fb: FormBuilder,
    private signupService: SignupService
  ) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      name: ['', Validators.required],
      email: [
        '',
        [Validators.required, Validators.email],
        this.validateEmailNotTaken.bind(this)
      ]
    });
  }

  validateEmailNotTaken(control: AbstractControl) {
    return this.signupService.checkEmailNotTaken(control.value).map(res => {
      return res ? null : { emailTaken: true };
    });
  }
}

我们的验证器与典型的自定义验证器非常相似。在这里,我们直接在组件 class 中定义了我们的验证器,而不是单独的文件。这使得访问我们注入的服务实例变得更加容易。还要注意我们需要如何绑定 this 值以确保它指向组件 class.

我们还可以在自己的文件中定义我们的异步验证器,以便于重用和关注点分离。唯一棘手的部分是找到一种方法来提供我们的服务实例。例如,在这里,我们创建了一个 class,它有一个 createValidator 静态方法,该方法接收我们的服务实例和 returns 我们的验证器函数:

异步-email.validator.ts

import { AbstractControl } from '@angular/forms';
import { SignupService } from '../signup.service';

export class ValidateEmailNotTaken {
  static createValidator(signupService: SignupService) {
    return (control: AbstractControl) => {
      return signupService.checkEmailNotTaken(control.value).map(res => {
        return res ? null : { emailTaken: true };
      });
    };
  }
}

然后,回到我们的组件中,我们导入我们的 ValidateEmailNotTaken class 我们可以像这样使用我们的验证器:

ngOnInit() {
  this.myForm = this.fb.group({
    name: ['', Validators.required],
    email: [
      '',
      [Validators.required, Validators.email],
      ValidateEmailNotTaken.createValidator(this.signupService)
    ]
  });
}

HTML 文件

<form [formGroup]="myForm">
  <input type="text" formControlName="name">
  <input type="email" formControlName="email">

  <div *ngIf="myForm.get('email').status === 'PENDING'">
    Checking...
  </div>
  <div *ngIf="myForm.get('email').status === 'VALID'">
     Email is available!
  </div>

  <div *ngIf="myForm.get('email').errors && myForm.get('email').errors.emailTaken">
     this email is already taken!
  </div>
</form>

表格

 public registerForm: FormGroup;
 constructor(private authService:AuthentificationService,
              private formBuilder: FormBuilder,
              ) { }

this.registerForm = this.formBuilder.group({
  firstname: ['', Validators.required],
  lastname: ['', Validators.required],
  username: ['', [Validators.required,this.validateUsername()]],
  email: ['', [Validators.required, Validators.email]],
  password: ['', [Validators.required, Validators.minLength(6)]],
  confirmPassword: ['', Validators.required]
  }, {
  validator: MustMatch('password', 'confirmPassword')
  }); 

  get f() { return this.registerForm.controls; } // convenience getter for easy access to form fields

验证者

 private validateUsername(): ValidatorFn {
    return (control: AbstractControl) => {
      if (control.value.length != 0) {
        this.authService.checkUsername(control.value).subscribe( data => { 
          if(data) control.setErrors({'alreadyExist': true}) ;
          else return null;
        })
      }else return null;
    }
  }

Html

  <mat-form-field>
          <input matInput placeholder="User Name" required autocomplete="off"  formControlName="username">
          <mat-icon matSuffix>perm_identity</mat-icon>
          <mat-error *ngIf= "f.username.errors?.required">
            Username is required
          </mat-error>
          <mat-error  *ngIf= " f.username.errors?.alreadyExist">
             this username already exists in our database
          </mat-error>
    </mat-form-field>