Angular表单定制验证器,空返回值未从表单中删除错误提示

7

我创建了一个自定义验证器来验证确认密码输入是否与原始输入匹配。它运行良好。但是,我允许两个字段都为空,因为这是在用户设置中更改密码的页面上,他们可能不想这样做。如果两个字段都为空,则表单应该变为有效状态,以便可以提交并更新其个人资料的其他设置,但发生了一些奇怪的事情。

表单属性:

passControl = new FormControl('', [
  FormValidation.checkPasswordStrength()
]);

passConfirmControl = new FormControl('', [
]);

profileForm = new FormGroup(
  {
    password: this.passControl,
    passwordConfirm: this.passConfirmControl
  },
  {
    validators: FormValidation.checkPasswordsMatch()
  }
);

这是我的验证函数:

static checkPasswordsMatch(): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} => {
    let passwordCtrl = control.get('password');
    let passwordConfirmCtrl = control.get('passwordConfirm');

    // allow blank for when they don't want to change password
    if (passwordCtrl.value === '' && passwordConfirmCtrl.value === '') {
      console.log('both are blank');
      return null;
    }

    if (passwordCtrl.value !== passwordConfirmCtrl.value) {
      console.log('hit mismatch passwords');
      control.get('passwordConfirm').setErrors( { passwordMatch: true } );
    }

    return null;
  };
}

因此,当表单加载时,它实际上是有效的,我看到两个都是空的。但是,如果您触摸密码字段并键入某些内容,当然它会显示它们不匹配,但是当您删除在那里键入的内容时,函数会显示它们再次都为空,但错误仍然存在,除非您还触摸密码确认字段并且也键入并删除一些内容。我错过了什么?

1个回答

7
你正在设置错误在 passwordConfirm FormControl 上,但是当你的验证器运行时,它并不影响该控件。如果你想让错误消失,你需要将验证器应用于该特定的 FormControl,或者确保在前一个测试成功时从控件中删除错误。
通常情况下,你会在验证器中返回错误,而不是在特定的 FormControl 上设置它。正如你所发现的那样,除非你手动从 FormControl 中删除错误,否则它会一直存在。验证器只会修改与其绑定的控件的错误对象。
通常情况下,如果/当出现错误,你只需返回错误即可。
return { passwordMatch: true };

或者,如果您想同时手动设置FormControl错误,请执行以下操作。

// allow blank for when they don't want to change password
if (passwordCtrl.value === '' && passwordConfirmCtrl.value === '') {
  console.log('both are blank');
  control.get('passwordConfirm').setErrors(null);
  return null;
}

if (passwordCtrl.value !== passwordConfirmCtrl.value) {
  console.log('hit mismatch passwords');
  control.get('passwordConfirm').setErrors( { passwordMatch: true } );
  return { passwordMatch: true }
}

还有一个小小的挑剔和追求严谨的问题,您应该尝试使您的错误逻辑上更容易理解。因此,在测试密码是否匹配时,说“passwordMatch: true”意味着密码匹配。您最好将错误命名为错误而不是测试,例如:passwordsDoNotMatch: true。这读起来好像存在密码不匹配的问题,这更准确地描述了通过表单呈现的问题。


太棒了,谢谢!你说得对,在我的其他验证器中,我是在每个控件上添加它们,但由于这个验证器涉及两个字段,所以我将其添加到表单本身。我实际上尝试手动清除错误,但有点偏差,因为我尝试直接从“errors”对象中删除该属性,但那样行不通。setErrors(null)就可以解决问题! - Aaron Hazelton
很高兴能帮忙!如果您得到的错误对象具有超过几个属性,则将整个对象设置为null可能不是理想的选择。因此,您可以始终将特定的错误设置为null passwordsDoNotMatch: null 以使其消失。此外,如果答案足够满意并/或彻底解决了问题,您会想要将其标记为答案,以让社区知道已经得到了回答。这也会给回答者声誉积分,这是回答问题的激励之一 :) - joshrathke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接