【问题标题】:Angular2: email already exist as custom Validator?Angular2:电子邮件已经作为自定义验证器存在?
【发布时间】:2017-06-10 09:06:01
【问题描述】:

我使用 Angular2 创建了一个表单,并创建了以下方法来检查电子邮件地址是否已经存在。这是我的代码:

checkEmail(): void {
    // FIRST PART
    this.found = false;
    // If user is not Premium...
    if (!this.currentUser.isPremium) {
        //  ...and if user typed something in the input field, then apply validitor for email address
        if (this.myForm.controls.email.value.length > 0) {
            this.myForm.controls.email.setValidators([validateEmail()]);
            this.myForm.controls.email.updateValueAndValidity();
        // If user leaves the input field blank or empty the typed input, then apply validator for required
        } else {
            this.myForm.controls.email.setValidators([Validators.required]);
            this.myForm.controls.email.updateValueAndValidity();
        }
    // If user is Premium...
    } else if (this.currentUser.isPremium) {
        // ...and if user typed something in the input field, then apply validitor for email address
        if (this.myForm.controls.email.value.length > 0) {
            this.myForm.controls.email.setValidators([validateEmail()]);
            this.myForm.controls.email.updateValueAndValidity();
        // If user leaves the input field blank or empty the typed input, then remove any validator
        } else {
            this.myForm.controls.email.setValidators(null);
            this.myForm.controls.email.updateValueAndValidity();
        }
    }

    // SECOND PART
    // If the input field is valid then check if the email already exist on server...
    if (this.myForm.controls.email.value.length > 0 && this.myForm.controls.email.valid) {
        this.loadingIcon = true;
        this.anagraficaService.getEmail(this.myForm.controls.email.value)
            .then(response => {
                let count = response.recordCount;
                if (count > 0) {
                    this.found = true;
                } else {
                    this.found = false;
                }
                this.loadingIcon = false;
            })
            .catch(error => {
                this.found = false;
                this.loadingIcon = false;
            });
    }
}

为了在模板文件中启用提交按钮,我检查myForm.validfound 是否设置为false

<button type="submit" class="ui primary button" (click)="onSubmit()" [disabled]="!myForm.valid || found">Submit</button>

现在,我想检查电子邮件地址是否已经存在,我的意思是将我的代码的第二部分放在一个外部文件(自定义验证器)中,然后仅在我的代码的第一部分检查电子邮件地址的有效性。像这样的:

this.myForm.controls.email.setValidators([validateEmail(), checkEmailExists()]);
this.myForm.controls.email.updateValueAndValidity();

您有更好的想法来达到相同的验证吗?关于这个问题的任何最佳实践?

谢谢。

【问题讨论】:

    标签: validation angular typescript angular2-forms reactive-forms


    【解决方案1】:

    哇。这与反应式表单验证的想法相去甚远。

    首先不要这样做

    this.myForm.controls.email.setValidators([validateEmail()]);
    this.myForm.controls.email.updateValueAndValidity();
    

    setValidatorsupdateValueAndValidity 是您几乎不应该调用的函数。它们仅适用于某些特定情况,例如动态表单行为。

    在你的情况下,你有一个静态表单,你应该用一些验证器描述。创建一个自定义异步验证器并将其分配给emailFormControl。这个验证器应该返回一个 Observable(或一个 Promise),当一切正常时它会解析为 null 或一个有错误的对象,例如{ emailAlreadyExists: true } 如果电子邮件存在,{ required: true } 或使用 Validators.required 和您的自定义异步验证的组合。

    最终你应该拥有

    ...
    public ngOnInit() {
      this.myForm = new FormGroup({
        email: new FormControl('', null, (control: FormControl) => {
          return new Promise((resolve, reject) => {
            // also add here is premium logic
            let requiredValidationResult = Validators.required(control);
    
            if (requiredValidationResult) {
              resolve(requiredValidationResult); // this will be {required: true}
              return;
            }
    
            // and here call your server and call
            //   resolve(null) in case it's fine
            //   resolve({ emailExists: true }) in case it's existing
          });
        })
      });
    }
    ...
    

    就是这样。

    【讨论】:

    • 使用您的解决方案,我是否必须将 LoginService 注入自定义验证器以查看用户是否为高级用户?请注意我的代码的第一部分。
    • 你不应该向验证器注入任何东西,因为 1. 它在你的组件的范围(闭包)中,LoginService 应该已经被注入,你可以在验证器中使用它作为this. currentUser 2。验证器不是注入目标,因为它不是组件/服务
    • 提交后如何调用自定义验证器?我的意思是,当我发布表单输入以创建用户时。 API 返回 Ok 或 KO,KO 可以是 401 -> '电子邮件已存在'。那么我该如何处理这个错误并调用验证器来设置它有错误 { emailExists: true } 并在模板中显示错误消息?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    • 2020-10-20
    • 2021-10-04
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多