【问题标题】:Validate Username Exist Async验证用户名是否存在异步
【发布时间】:2018-12-01 14:09:23
【问题描述】:

我正在尝试通过异步验证器说明用户名是否可用来验证用户名,我尝试了很多解决方案,但我不知道如何完成这项工作,我有这个错误:

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>

【问题讨论】:

标签: angular asynchronous rxjs angular-reactive-forms


【解决方案1】:

这是给你的例子

一个简单的组件初始化我们的响应式表单并定义我们的异步验证器: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 };
    });
  }
}

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

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

async-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 类,我们可以像这样使用我们的验证器:

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>

【讨论】:

  • 感谢您的回答,我确实尝试了该解决方案,但此代码中缺少某些内容以使其正常工作,到目前为止我想通了。
  • 用解释更新了答案。谢谢!
【解决方案2】:

表格

 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>

【讨论】:

  • 欢迎来到 Stack Overflow。 Stack Overflow 上不鼓励仅使用代码的答案,因为它们没有解释它是如何解决问题的。请编辑您的答案以解释此代码的作用以及它如何回答问题,以便它对 OP 以及其他有类似问题的用户有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多