使用反应形式的不同根控件进行自定义验证

Custom validation with different root controls in reactive forms

我有 heroForm,其中包含表单数组 entities。每一项都是FormGroup

示例如下:

this.heroForm = this.fb.group({
      entities: this.fb.array([]),
    });

以下是我向数组添加新组的方法:

  addEntity() {
    this.entities.push(this.createFormGroup(new Address()));
  }

以下是我创建单个组的方式:

  createFormGroup(address: Address) {
    return this.fb.group({
      'street': new FormControl(address.street, []),
      'city': new FormControl(address.city, [duplicateCity]),
      'state': new FormControl(address.state, []),
      'zip': new FormControl(address.zip, [])
    });
  }

这是自定义验证函数:

function duplicateCity(input: FormControl): any {
  if (!input.root || !(<FormGroup>input.root).controls) {
    return null;
  }

  // Do some validation.
  input.value === ...
}

现在我想遍历 City 槽控件并比较它们的值。如果我发现城市名称出现两次,我想 return 错误。

问题是我不想比较相同的控件,我想跳过它。执行此操作的准确方法应该是什么?

实际上我错过了这部分:

function duplicateCity(id: number): any {
  return (control: AbstractControl): { [key: string]: any } => {
    if (!control.root || !(<FormGroup>control.root).controls) {
      return null;
    }

    // Do some logic

  };

函数 duplicateCity(id: number) 现在是 returns 验证函数的工厂。我可以在创建表单组期间动态地将 ID 作为参数传递,如下例所示:

createFormGroup(address: Address, id: number) {
    return this.fb.group({
      'street': new FormControl(address.street, []),
      'city': new FormControl(address.city, [duplicateCity(id)]),
      'state': new FormControl(address.state, []),
      'zip': new FormControl(address.zip, [])
    });