在formArray内验证formGroup的问题

时间:2019-01-01 17:53:15

标签: angular angular-reactive-forms angular-validation

我正在创建带有角形物料垫的表格。

我在编写应用程序时使用的是响应式表单,表单启动看起来像这样:

myForm = this.fb.group({
    settings: this.fb.array([])
});

我的表单是一个formGroup,其中包含一个formArray控件(设置)。

设置formArray包含每个设置的formGroup(mat-table中的每一行是一个formGroup并包含许多控件)。

当我尝试向其添加验证时,我的问题就开始了。

如果我刚好有一个内部带有formControl的formGroup,并且其中一个是Validators。例如,该表单是无效的,直到我添加了一些值,然后它将变为有效状态。

但是,在表单数组中使用formGroup时,即使在require字段中添加了一些值之后,表单状态仍然无效(我什至通过控制台记录表单,以查看内部值是否被更改了)。

此外,当我尝试使用valueChange()。subscribe捕获更改时,仅当我从formArray推入/删除组时才触发该事件,而在更改设置组内的现有控件时则从未触发该事件。

我该如何侦听数组中各组的内部变化事件,然后对它们使用一些自定义评估?

4 个答案:

答案 0 :(得分:2)

在没有看到更多代码的情况下,很难猜测出什么问题了。

但这是我的一些代码供参考:

组件代码

  get addresses(): FormArray {
    return <FormArray>this.customerForm.get('addresses');
  }

  ngOnInit() {
    this.customerForm = this.fb.group({
      firstName: ['', [Validators.required, Validators.minLength(3)]],
      lastName: ['', [Validators.required, Validators.maxLength(50)]],
      addresses: this.fb.array([this.buildAddress()])
    });
  }

  addAddress(): void {
    this.addresses.push(this.buildAddress());
  }

  buildAddress(): FormGroup {
    return this.fb.group({
      addressType: 'home',
      street1: ['', Validators.required],
      street2: '',
      city: '',
      state: '',
      zip: ''
    });
  }

模板

    <div formArrayName="addresses"
         *ngFor="let address of addresses.controls; let i=index">

        <div class="form-group row mb-2">
          <label class="col-md-2 col-form-label"
                 attr.for="{{'street1Id' + i}}">Street Address 1</label>
          <div class="col-md-8">
            <input class="form-control"
                   id="{{'street1Id' + i}}"
                   type="text"
                   placeholder="Street address (required)"
                   formControlName="street1"
                   [ngClass]="{'is-invalid': (address.controls.street1.touched || 
                                              address.controls.street1.dirty) && 
                                              !address.controls.street1.valid }">
            <span class="invalid-feedback">
              <span *ngIf="address.controls.street1.errors?.required">
                Please enter your street address.
              </span>
            </span>
          </div>
        </div>
    </div>

您可以在此处找到完整的项目:https://github.com/DeborahK/Angular-ReactiveForms/tree/master/Demo-Final

答案 1 :(得分:1)

我正在做以下事情!!

const array = (this.fg.get('addresses') as FormArray).controls;
array.push(this.fb.group({...}));

应该是(没有controls

const array = (this.fg.get('addresses') as FormArray);
array.push(this.fb.group({...}));

答案 2 :(得分:0)

您使用的嵌套结构不应影响验证规则。如果FormControl无效,则无效状态将冒泡到根AbstractControl(在本例中为“ myForm” FormGroup)。 Angular将为您处理所有这一切。

请使用与您描述的表单结构相同的形式查看此stackblitz示例:https://stackblitz.com/edit/angular-xhppjs?file=src%2Fapp%2Fapp.component.html

奖金信息:

不要尝试捕获valueChanges以强制执行验证规则。如果您仅按Angular的方式使用验证器函数,则将拥有更轻松的时间。 (https://angular.io/guide/form-validation#reactive-form-validation

以下是Angular内置列表:https://angular.io/api/forms/Validators

如果内置功能不适合您的需求,请参见以下部分:创建自定义验证器功能:https://angular.io/guide/form-validation#custom-validators

答案 3 :(得分:0)

感谢您的回复,我设法解决了html文件中的问题。

当我启动mat-table时,我做了以下事情: [dataSource] = settings.value

这样做可以在表格中显示值,但没有更新formArray中的控件...

我通过将其更改为settings.controls来解决它,并向每个mat-cell添加了[formGroupName] = index

感谢您的帮助。