在使用 Angular Reactive Forms 的跨字段验证时如何对所有表单控件强制执行必需的验证

问题描述

我有一个表单,其中所有字段都是下拉列表并且都是必需的。还有一个条件是两个不同控件之间的值必须相同。我添加一个自定义验证器来利用跨字段验证,但我遇到的问题是,如果用户使用特殊规则回答问题,它会将整个表单 (FormGroup) 标记为有效,即使仍有下拉列表没有还没摸过。

如何在要求所有字段都具有值的同时维护跨字段验证?我看到的所有示例都是非常简单的 2 个字段表单,它们匹配密码/确认或日期范围。我的表单有大约 30 个字段。

创建动态表单的代码

      questions.forEach(question => {
        question.questions.forEach(child => {
          group[child.key] = new FormControl({ key: child.value } || '',Validators.required);
        });
      });

      return new FormGroup(group,[compareValues('26','27','Questions 4 and 5 must have the same answer.')]);
    }

自定义验证器:

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

export function compareValues(val1: string,val2: string,message: string): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const mustMatch1 = control.get(val1);
    const mustMatch2 = control.get(val2);

    if (mustMatch1 && mustMatch2) {
      return mustMatch2.value === '' || mustMatch1.value.key === mustMatch2.value.key ? null : { mustMatch: true,message: message }
    }
  };
}

解决方法

正如我在上面的评论中提到的,这是由于我在 FormControl 初始化中遇到的错误导致的验证过程中的误解。

事实证明 FormControl 始终具有有效值。即使 child.value 未定义或空字符串,总会有一个对象设置了一个键,该对象仍然被认为是我如何设置的有效条目。

以下是我所做的一项更改,它清理了验证,并使其按我预期的方式工作。

改变上一个:

  questions.forEach(question => {
    question.questions.forEach(child => {
      group[child.key] = new FormControl({ key: child.value } || '',Validators.required);
    });
  });

以下内容:

  questions.forEach(question => {
    question.questions.forEach(child => {
      group[child.key] = new FormControl(child.value ? { key: child.value } : '',Validators.required);
    });
  });

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...