在 Angular 中以动态反应形式添加项目

Add item in dynamic reactive form in Angular

我正在尝试在 Angular 中构建一个嵌套的反应式表单 5. 我能够在一级推送项目,但无法在二级推送项目。

ngOnInit() {
 this.orderForm = this.formBuilder.group({
  customerName: '',
  email: '',
  items: this.formBuilder.array([this.createItem()])
});
}

 createItem(): FormGroup {
    return this.formBuilder.group({
      name: 'a',
      description: 'b',
      price: 'c',
      //subItems: this.formBuilder.array([this.createSubItem()])
    });
 }

 //createSubItem(): FormGroup {
    //return this.formBuilder.group({
      //subname: 'abc'
    //});
 //}

 addItem(): void {
    this.items = this.orderForm.get('items') as FormArray;
    //this.subItems = this.items.get('subItems') as FormArray;
    //this.subItems.push(this.createSubItem());
    this.items.push(this.createItem());
 }

在上面的代码中,未注释的代码在推送时运行良好。我在项目中有更多的子项目,注释代码是我想要实现的代码,但它不起作用。

任何人都可以告诉我如何实现这一目标吗?

对于未注释的代码,我像这样在 html 中显示数据并且运行良好。如果任何机构在代码级别有解决方案,也请告诉我如何更新嵌套项目的 html。

<form [formGroup]="orderForm">
<div formArrayName="items" *ngFor="let item of orderForm.get('items').controls; let i = index;">
    <div [formGroupName]="i">
      <input formControlName="name" placeholder="Item name">
      <input formControlName="description" placeholder="Item description">
      <input formControlName="price" placeholder="Item price">
    </div>
  </div>
  <input type="button" value="sldkj" (click)="addItem()">
</form>

解决方案:

首先,我设法像这样预填充值。

 obj = [
    {
      'name': "umair",
      'description': "desc1",
      'subItems': [
        {
          'subname': 'value'
        },
        {
          'subname': 'value2'
        },
        {
          'subname': 'value3'
        }
      ]
    },
    {
      'name': "ali",
      'description': "desc2",
      'subItems': [
        {
          'subname': 'valu4'
        },
        {
          'subname': 'value5'
        },
        {
          'subname': 'value6'
        }
      ]
    }
  ]

  ngOnInit() {
    this.createForm(this.obj);
    console.log(this.orderForm);
  }

  createForm(obj) {
    var arr = [];
    for (var i = 0; i < obj.length; i++) {
      arr.push(this.createItem(obj[i]));
    }
    this.orderForm = this.formBuilder.group({
      items: this.formBuilder.array(arr)
    });
  }

  createItem(obj): FormGroup {
    var subArr = [];
    for (var i = 0; i < obj.subItems.length; i++) {
      subArr.push(this.createSubItem(obj.subItems[i]));
    }
    return this.formBuilder.group({
      name: obj.name,
      description: obj.description,
      subItems: this.formBuilder.array(subArr)
    });
  }

  createSubItem(subItem): FormGroup {
    return this.formBuilder.group({
      subname: subItem.subname
    });
  }

在得到下面 'marked' 回答的帮助后,我成功地添加了子项目并填充到 html 中,如下所示。

 <form [formGroup]="orderForm">
  <!-- <label>{{item.get('name').value}}</label> -->
  <div formArrayName="items" *ngFor="let item of orderForm.controls.items.controls; let i = index;">
    <div formGroupName="{{i}}">
      <!-- <label>{{item.get('name').value}}</label> -->
      <input formControlName="name" placeholder="Item name">
      <input formControlName="description" placeholder="Item description">

      <input type="button" value="subAdd" (click)="addSubItems(i)">

      <div formArrayName="subItems" *ngFor="let subItem of item.controls.subItems.controls; let idx = index;">
        <div formGroupName="{{idx}}">
          <!-- <label>{{subItem.get('subname').value}}</label> -->
          <input formControlName="subname" placeholder="Item name">
        </div>
      </div>

    </div>
  </div>
</form>

代码

addSubItems(_index: any): void {
    var a = this.orderForm['controls']['items']['controls'][_index] as FormGroup;
    this.subItems = a.get('subItems') as FormArray;
    var newSubItem = {
      'subname': 'value6'
    }
    this.subItems.push(this.createSubItem(newSubItem));
  }

所以首先让我们从了解您的工作开始。

你在 formarray 中创建了一个 formarray。所以这意味着它有 两个循环 。所以你必须 *ngFor 第一个和 *ngFor 第二个。最后,这意味着您的项目有 index i,子项目有 j。然后你可以添加 addSubItems(i) 来推送你的子项。

您的 html 应如下所示:

<form [formGroup]="orderForm">
  <div formArrayName="items">
     <div *ngFor="let arrays of orderForm.controls.items.controls; let i = index;">
        <div formGroupName="{{i}}">
          <input formControlName="name" placeholder="Item name">
          <input formControlName="description" placeholder="Item description">
          <input formControlName="price" placeholder="Item price">
          <input type="button" value="subAdd" (click)="addSubItems(i)"> <-- here your button -->
          <div formArrayName="subItems">
             <div *ngFor="let item of arrays.controls.subItems.controls; let j = index;">
                <div formGroupName="{{j}}">
                   <input formControlName="subname" placeholder="Item subname">

您的 addSubItems 应该类似于:

 addSubItems(_index: any): void {
    this.item = this.orderForm['controls']['items']['controls'][_index] as FormGroup;
    this.subItems = this.item.get('subItems') as FormArray;
    this.subItems.push(this.createSubItem());

为了减少代码量,这些可以稍微重构一下addSubItems(index) to addSubItems(item):

<form [formGroup]="orderForm">
  ...
  <div formArrayName="items" *ngFor="let item of orderForm.controls.items.controls; let i = index;">
      ...
      <input type="button" value="subAdd" (click)="addSubItems(item)">
  </div>
  ...
</form>

addSubItems(item: FormGroup): void {    
    this.subItems = item.get('subItems') as FormArray;
    var newSubItem = {
      'subname': 'value6'
    }
    this.subItems.push(this.createSubItem(newSubItem));
  }

因此,无需按索引查找项目:var a = this.orderForm['controls']['items']['controls'][_index] as FormGroup;,因为您已经可以通过 item: FormGroup

StackBlitz Demo