Angular 表单自定义验证器 null return 未从表单中删除错误

Angular forms custom validator null return not removing error from form

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

表单道具:

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;
  };
}

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

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

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

通常你会 return 它发生的错误 if/when。

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。这看起来好像密码不匹配,这是对通过表单呈现的问题的更准确描述。