【问题标题】:Angular 6 error: ValidatorFn expected to return a promiseAngular 6 错误:ValidatorFn 期望返回一个承诺
【发布时间】:2019-05-05 09:42:42
【问题描述】:

我遇到了一个问题,即验证器函数期望返回一个承诺。据我了解,我正在创建一个自定义验证器函数,该函数使用承诺检查输入的“新密码”字符串是否等于“确认密码”字符串。这是我的代码的当前状态:

change-password.component.ts

import { FormBuilder, FormGroup, Validators, AbstractControl } from '@angular/forms';
import { passwordValidator } from './password.validator';

export class ChangePasswordComponent implements OnInit {

  form: FormGroup;

  constructor(formCreator: FormBuilder) { 

    this.form = formCreator.group({
    oldPassword: ['', [ Validators.required, Validators.minLength(4) ], passwordValidator.isSameOld],
    newPassword: ['', [ Validators.required, Validators.minLength(4)] ],
    confirmPassword: 
                 ['', [ Validators.required, Validators.minLength(4)], 
                        passwordValidator.isSameNew ] 
    });
  }

password.validator.ts

在 Jaime 的帮助下添加的内容

    import { AbstractControl, ValidationErrors, FormControl, ValidatorFn } from "@angular/forms";

    static isSameNew(formFields: FormGroup) : Promise<ValidationErrors | null>{ 
        return new Promise((resolve, reject) => {

            setTimeout(() => {
                console.log(formFields.get('newPassword'));

                if (formFields.get('confirmPassword').value !== formFields.get('newPassword').value) {
                    console.log(formFields);

                    resolve({isSameNew: true});
                }

                else resolve(null);
            }, 2000)

        });
    }

你能帮我调试一下吗?我尝试通过编写

将 newPassword 传递给函数
    confirmPassword: 
                 ['', [ Validators.required, Validators.minLength(4)], 
                        passwordValidator.isSameNew(newPassword) ] 

但很快发现我不能这样做,因为直到定义表单对象之后才定义 newPassword 属性。我需要使用一个 Promise,以便我可以使用异步回调函数在“密码不匹配”错误消息出现之前延迟一下,以免吓到用户。

非常感谢您抽出宝贵时间

【问题讨论】:

    标签: angular validation promise passwords


    【解决方案1】:

    如果要比较两个不同控件的值,应将验证器附加到 group 而不是其中一个控件。

    试试这样的:

      // Your component constructor:
      constructor(formCreator: FormBuilder) { 
        this.form = formCreator.group(
          {
            oldPassword: ['', [ Validators.required, Validators.minLength(4) ]],
            newPassword: ['', [ Validators.required, Validators.minLength(4)] ],
            confirmPassword: ['', [ Validators.required, Validators.minLength(4)], passwordValidator.isSameNew ] 
          },
          {
            validator: PasswordMatchValidator
          }
        );
      }
    
      // password-match.validator.ts:
      export function PasswordMatchValidator(formGroup: FormGroup): void {
        const newPassword = formGroup.get('newPassword').value;
        const confirmPassword = formGroup.get('confirmPassword').value;
    
        formGroup.get('confirmPassword').setErrors(undefined);
    
        if (newPassword !== confirmPassword) {
          formGroup.get('confirmPassword').setErrors({ match: true });
        }
      }
    

    您可以使用相同的方法来比较旧密码和新密码,并相应地设置isSameNew

    另外请注意,如果你想返回一个承诺,你应该使用AsyncValidatorFn 接口而不是ValidatorFn 接口。

    【讨论】:

    • 我今天试着写了这个函数,但是 formGroup.get('confirmPassword') 和 formGroup.get('newPassword') 返回 null
    • @Bobstar89 你能在 JSFiddle 上分享你的代码链接吗?
    • jsfiddle.net/s4q3u8nh 我对 JSFiddle 还很陌生,所以请原谅任何低效
    【解决方案2】:

    我最终通过调用 formFields 的 root 方法解决了这个问题,如下所示:

        static isSameNew(formFields: FormGroup) : Promise<ValidationErrors | null>{ 
        return new Promise((resolve, reject) => {
    
            setTimeout(() => {
    
                if (formFields.root.get('confirmPassword').value !== formFields.root.get('newPassword').value) {
                    resolve({isSameNew: true});
                }
    
                else resolve(null);
            }, 2000)
    
        });
    

    我不完全知道为什么使用“root”解决了我的问题,但据我所知,每个 FormGroup 都知道其父 Form 的控件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-27
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 2016-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多