【问题标题】:Angular2 Formbuilder - Referencing FormArray ElementAngular2 Formbuilder - 引用 FormArray 元素
【发布时间】:2017-03-21 03:11:05
【问题描述】:

我们有一个接受服务响应的表单,以便用正确的字段名称填充表(我们的 FormArray)。给定正确的表单字段名称,我们正在尝试使用对不同数据库的另一个服务调用来填充某些参数的字段。

一个简单的例子:

ngOnInit() {
  this.myForm = this._fb.group({
    name: [''],
    myArray: this._fb.array([])
  }),
  initArray();
}
private initArray(){
  this.arrayValsService.getValues.subscribe(
    response => {
                  for (item of response) {
                    let arrayItemGroup = this.createItemGroup(item.code, item.value);
                    const control = <FormArray>this.myForm.controls['myArray'];
                    control.push(arrayItemGroup);
                  }
                },
    err => {console.error(err);}
  };
}
private createItemGroup(code: string, value: string) {
  return this._fb_group({
    selected: [false],
    itemCode: [code],
    itemValue: [value],
    otherVal1: [''],    
    otherVal2: ['']  
  });
}

private setArray() {
  if(this.key !== undefined) {
    this.dataService.getData(this.key).subscribe(
      response => { 
        this.myForm.patchValue(response);
        for (let resItem of response.itemsSet) { 
          for (let formItem of <FormArray>this.myForm.controls['myArray']) {
            if (formItem.controls.itemCode === resItem.code) { // <== ISSUE HERE
              formItem.patchValue(response.itemsSet.resItem);
              formItem.controls.selected.setValue(true);
            }
          }
        }
      err => {console.error(err);}
    );
  }
}

我在控制台中收到一个错误,我们“无法读取未定义的属性 'controls'”,出现在上面的标记行上。我需要引用数组中的各个表单控件组,以便相应地更新它们的值。除了使用嵌套的 for 循环,我还尝试使用 array.find 来检查数组元素组中的特定控件:

const control = <FormArray>(this.myForm.controls['myArray'])
  .find(item => myArray.controls.item.itemCode === resItem.code)

这也不行;遇到同样的问题,控件是未定义的属性。底线是,我需要一种方法来引用 formArray 的子元素和每个子元素的控件。

以下方法适用于遍历 formArray.controls 数组对象,但仍会产生 typescript 编译错误:

for (let resItem of response.itemsSet) {
  const control = this.myForm.controls['myArray'].controls
    .find((item:any) => item.value.itemCode === resItem.code);
  if(control) {control.controls.selected.setValue(true); // ...other value updates

control 是一个数组对象,所以 .find() 在这里工作。在['myArray'].controls 的子项(FormGroup 类型)中,还有另一个数组对象 child.value,其中包含我正在比较服务响应的代码。从功能上讲,这是在做预期的工作;但是,我仍然收到错误消息:“错误 TS2329:“AbstractControl”类型上不存在属性“控件”。”

最终编辑以供将来参考:

对 FormArray 本身和我正在“寻找”的 FormGroup 进行类型转换可以有效地消除最初的打字稿错误。然而,在这样做之后,我正在更新的表单控件开始抛出相同的“在类型‘AbstractControl’上的属性‘控件’”错误。我根据this question更改了引用特定控件的格式。

最终结果:

for (let resItem of response.itemsSet) {
      const control = (<FormGroup>((<FormArray>(this.myForm.controls['myArray'])).controls
        .find((item:any) => item.value.itemCode === resItem.code)));
      if(control) {control.controls['selected']setValue(true); // ...other value updates

关键要点:类型转换 FormGroups、FormArrays;引用具有 ['control'] 格式的显式命名控件。

【问题讨论】:

    标签: angular angular2-forms formbuilder


    【解决方案1】:

    您拥有的formItem 变量不是FormControl。那么解决方案就是直接访问 FormArray 上的 controls 数组并进行迭代:

    for (let formItem of <FormArray>this.myForm.controls['myArray'].controls) {
        if ((<FormGroup>formItem).controls['itemCode'] === resItem.code) {
              <...>
              (<FormGroup>formItem).controls['selected'].setValue(true);
        }
    }
    

    如果你记录它们,另一种方式应该会弹出一堆“未定义”。

    这里有一个 plunker 展示了这种微妙之处:http://plnkr.co/edit/JRbrPR2g2Kl3z6VJV5jQ?p=preview

    对于您的 TypeScript 错误,如果您比编译器更了解,那么您将不得不强制转换。

    这里是查找版本:

    (<FormGroup>control).controls['selected'].setValue(true);
    

    【讨论】:

    • 遵循这个模式让我遇到了几个 ts 错误:Type 'FormArray' 不是数组或字符串; “AbstractControl”类型上不存在属性“控件”。在您的 plnkr 中,您没有将 ['myArray'].controls 转换为 &lt;FormArray&gt; (我相信它是数组类型)。我删除了该转换,但仍然收到 AbstractControl 类型的错误,并且该方法没有产生预期的结果。我将使用功能足够但仍会产生相同错误的方法来编辑问题。
    • 你试过铸造吗?如果您比编译器更了解,您将不得不告诉它。更新了答案以提供示例。
    猜你喜欢
    • 2018-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2021-10-07
    • 1970-01-01
    • 2018-02-08
    • 2017-05-18
    相关资源
    最近更新 更多