实现 Angular 跨域验证的最佳方式

Hey*_*ojo 2 reactive-forms angular angular-reactive-forms

我试图找出在 Angular 中实现跨领域验证的最佳方法。

例如,我有一个选择字段,它使另一个字段成为必填字段。

我希望能够:

  • 如果无效,更改字段的边框颜色
  • 每当它成为必需时,在字段前显示 *
  • 显示一条特定的错误消息,说明违反了哪些验证规则。

到目前为止,我想出了三个解决方案,但它们对我来说并不那么令人信服。

  • 收听选择字段更改并更新第二个字段的验证器。
  • 监听两个字段的变化并手动执行 setErrors
  • 将验证提升到 formGroup(这可能会感觉非常麻烦,因为验证状态现在存储在 formGroup 中,而不是直接在 formControl 中可用)。

这是一个Stackblitz实现,它演示了我的调查。

Eli*_*seo 6

更新 - 更好的方法

创建customValidator表单并使用验证器来使用setError所需的控件。使用setError, 使 Angularng-invalid为我们添加,我们不需要订阅值更改。看:

form: FormGroup = new FormGroup(
  {
    input1: new FormControl('optional'),
    input2: new FormControl(null),
  },
  { validators: this.customValidatorForm() },
);

customValidatorForm() {
  return (form: FormGroup) => {
    const error =
      form.get('input1').value != 'optional' && !form.get('input2').value
        ? { required: true }
        : null;
    form.get('input2').setErrors(error); //<--see the setErrors
    return error;
  };
}
Run Code Online (Sandbox Code Playgroud)

堆栈闪电战

旧答案

只需使用一个customValidator喜欢:

form: FormGroup = new FormGroup({
  input1: new FormControl('optional'),
  input2: new FormControl(null, this.customValidator()),
});

customValidator() {
  return (control: any) => {
    if (!control.parent) return null;

    let mandatory = control.parent.get('input1').value;
    return mandatory != 'optional' && !control.value ? { required: true } : null;
  };
}
Run Code Online (Sandbox Code Playgroud)

不要求control.parent使用的另一种选择.bind(this)。这允许我们在验证器内部访问我们组件的所有变量,当然还可以访问this.form

form: FormGroup = new FormGroup({
  input1: new FormControl('optional'),
  input2: new FormControl(null, this.customValidator().bind(this)), //<--bind(this)
});

customValidatorBind() {
  return (control: any) => {
    if (!this.form) return null;

    let mandatory = this.form.get('input1').value;
    return mandatory != 'optional' && !control.value ? { required: true } : null;
  };
}
Run Code Online (Sandbox Code Playgroud)

好吧,因为我们希望在input1 input2检查更改时,您需要使用,在创建表单后订阅valueChanges

this.form.get('input1').valueChanges.subscribe(() => {
  this.form.get('input2').updateValueAndValidity();
});
Run Code Online (Sandbox Code Playgroud)