Angular 表单自定义验证器 null 返回不会从表单中删除错误

Aar*_*ton 5 javascript custom-validators typescript angular angular-reactive-forms

所以我创建了一个自定义验证器来验证确认密码输入是否与原始条目匹配。工作正常。但是,我允许这两个字段都为空,因为这是在某人可以在其设置中更改密码的页面上,当然他们可能不想这样做。如果两者都为空白,则表单应该有效,以便可以提交,并且可以为他们的个人资料更新其他设置,但发生了一些奇怪的事情。

表格道具:

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

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

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

这是我的验证功能:

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;
  };
}
Run Code Online (Sandbox Code Playgroud)

所以当表单加载时,它实际上是有效的,我看到both are blank. 但是,如果您触摸密码字段并输入一些内容,当然它表明现在它们不匹配,但是当您删除在那里输入的内容时,该功能会显示它们再次都是空的,但是错误仍然存​​在并且表单保持无效,除非您还触摸 passwordConfirm 字段并输入一些内容并将其删除。我错过了什么?

jos*_*hke 6

您正在passwordConfirmFormControl上设置错误,您的验证器在运行时不会影响该错误。如果您希望错误消失,您需要将验证器应用于该特定 FormControl,或者您需要确保在之前的测试成功时从控件中删除错误。

通常,您会在验证器中返回错误,而不是在特定的 FormControl 上设置它。正如您所发现的,除非您从 FormControl 中手动删除错误,否则它会一直存在。验证器只会改变它们所绑定的控件的错误对象。

通常,如果/当它发生时,您只会返回错误。

return { passwordMatch: true };
Run Code Online (Sandbox Code Playgroud)

或者,如果您想同时执行这两项操作并手动设置 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 }
}
Run Code Online (Sandbox Code Playgroud)

也只是一个挑剔的迂腐的东西,你应该尝试使你的错误在逻辑上可读。因此,当您测试密码是否匹配时,说passwordMatch: true暗示密码匹配。你可能会关闭错误,而不是测试,例如命名后,你的错误,更好: passwordsDoNotMatch: true。这读起来好像密码不匹配,这是对通过表单呈现的问题的更准确描述。