如何在表单控件中动态创建表单控件并将它们与 ngFor 中的其他数据一起显示?

How to dynamically create form controls in a form control and display them along other data within an ngFor?

我想 运行 一个对象数组上的 ngFor,以便用每个对象对应的数据填充标签,最好在同一个 ngFor 中,我想为每个对象添加一个表单控件上述数组。我还希望能够为添加的每个新对象添加一个新的表单控件。据我了解,执行上述操作的逻辑一切正常,我的问题是能够同时适当地遍历对象数组和表单控件数组?

下面是为数组中的每个对象创建新表单控件的逻辑:

首先,我在 ngOnInit 中的 FormGroup 中初始化了 FormArray,如下所示:

stockForm: FormGroup;

ngOnInit(): void {
    this.stockForm = new FormGroup({
      'quantities': new FormArray([])
    })
    this.getBranchStock();
  }

然后我声明了两个方法,一个用于获取控件,另一个用于为上述 FormArray 创建控件。

提到的第一种方法(获取控件):

getQuantityControls() {
    return (<FormArray>this.stockForm.get('quantities')).controls;
  }

然后,提到的第二种方法(创建控件):

createNewQuantity() {
    const quantity = new FormControl('', [Validators.required]);
    (<FormArray>this.stockForm.get('quantities')).push(quantity)
  }

第二种方法“createNewQuantity”,将一个新的表单控件推送到表单数组。当我收到我之前谈到的对象数组时,最初会调用此方法。我通过 for 循环 运行 为数组中的每个对象调用“createNewQuantity”方法,如下所示:

product: BranchProduct[];

 getBranchStock() {
    const id = this.branchService.getBranchId();
    id.subscribe(
      (resp: any) => {
        this.subs.add(this.branchService.getBranchStock(resp).subscribe(
          (resp: any) => {
            this.product = resp;
            for (var i = 0; i < this.product.length; i++) {
              this.createNewQuantity();
            }
          },
          (error: HttpErrorResponse) => {
            console.log(error);
          })
        )
      })
  }

以上执行后,数组中的每个对象都有一个表单控件。这按预期工作(据我所知)。我真正的问题在于我 运行 ngFor 循环的方式。如上所示,我需要遍历 'product' 数组中的所有对象,以及 'quantities' FormArray 中每个新创建的表单控件。我不知道如何设置模板来让它工作。我尝试过的是以下内容:

<form [formGroup]="stockForm" *ngIf="stockForm">
              <mat-card *ngFor="let item of product; let quantity of getQuantityControls(); let i = index;" class="enter-quantity-card">
                  <mat-grid-list cols="5" rowHeight="7:1">
                    
                      <!-- Product Id Tile-->
                      <mat-grid-tile>
                        <div class="data-wrapper">
                          <h3>Product ID: <span class="data-text"><strong>{{item.ProductId}}</strong></span></h3>
                        </div>
                      </mat-grid-tile>

                      <!-- Product Type Tile -->
                      <mat-grid-tile>
                        <div class="data-wrapper">
                          <h3>Product Type: <span class="data-text"><strong>{{item.ProductTypeName}}</strong></span></h3>
                        </div>
                      </mat-grid-tile>

                      <!-- Product Name Tile-->
                      <mat-grid-tile>
                        <div class="data-wrapper">
                          <h3>Product Name: <span class="data-text"><strong>{{item.ProductName}}</strong></span></h3>
                        </div>
                      </mat-grid-tile>

                      <!-- Quantity On Hand Tile-->
                      <mat-grid-tile>
                        <div class="data-wrapper">
                          <h3>Quantity on Hand: <span class="data-text"><strong>{{item.QuantityOnHand}}</strong></span>
                          </h3>
                        </div>
                      </mat-grid-tile>

                      <!-- Quantity Selected Tile (Using Form Array) -->
                      <mat-grid-tile>
                        <mat-form-field>
                          <input matInput [formControlName]="i">
                        </mat-form-field>
                      </mat-grid-tile>

                  </mat-grid-list>
              </mat-card>
          </form>

由于我在一个 ngFor 中同时具有 let item of productlet quantity of getQuantityControls(); let i = index; 声明,因此上述内容不起作用。 Typescript 不允许这样做,因为新的 AbstractControl 不能是产品数组类型。但是,我根本不知道我还能如何构造模板以使其工作。表单本身看起来像这样:

所以正如你所看到的,每个对象'has its own'形成了控件。但是我不知道如何使每个表单控件唯一以便单独验证每个控件。感谢任何帮助。

如何使用 index 而不是遍历 product 数组来获取每个产品?

你只有一个循环:*ngFor="let quantity of getQuantityControls(); let i = index;" 然后像这样使用 index{{product[i].ProductTypeName}}