首页 > 解决方案 > 如何使用angular8将对象数组绑定到formGroup和formarray

问题描述

嗨,我已经使用响应式表单将对象数组绑定到 formArray,但是在这里,如果我选择一个部分中的任何一项并单击向右移动/向左移动,则整个对象已从一个部分移动到另一个部分。但是该功能运行良好,但我无法在 form.valuechanges() 中检测到从一个部分到另一个部分的更改。如果项目已从一个部分移动到另一个部分,任何人都可以帮助我检测更改,在这里我想要更改检测,但功能必须按原样工作,我的意思是整个对象从一个部分移动到另一个部分。

提前致谢。

我在这里工作 demo2,我希望我之前发布的 demo1 像这个 demo2 一样工作,并且 formarray 工作。 演示 2

演示: 演示 1

TS:

 private settingsGroupInfoForm() {
    if (!this.agentDetailsList) {
      // Add
     this.agentGroupViewInfoForm = this.FB.group({
          agentGroupView: this.FB.array(
            this.agentInView.map(x=>(x))
          ),
        })
    } else {
      // Edit
      if (this.agentDetailsList) {

       this.agentGroupViewInfoForm = this.FB.group({
          agentGroupView: this.FB.array(this.agentInView.map(x=>(x))),

      })
      }
      this.agentGroupViewInfoForm.valueChanges.subscribe(data => {
          this.formEdit = true;
          console.log('agentGroupViewInfoForm', this.formEdit)
        })
      }
    }

HTML:

 <div class="card-body overflow-auto py-0" *ngIf="agentGroupViewInfoForm"
            [formGroup]="agentGroupViewInfoForm">
                <ul class="list-group list-group-flush" *ngFor="let child of agentInView"   name="agentInGroup" formArrayName="agentGroupView">
                  <li class="list-group-item {{isInActiveItems(child) ? 'active' : ''}}" (click)="toggleActiveItem(child)">
                    {{child.value}}
                  </li>
                </ul>
              </div>

标签: angularangular-reactive-forms

解决方案


你的问题

  • 您有 2 个相同类型的项目数组
  • 您想为每个数组呈现一个表单数组
  • 您希望能够在数组之间移动项目
  • 您希望能够将表单值绑定回提交的项目

该设计

与 Angular 中几乎所有基于组件的问题一样,您应该首先考虑模型。您的模型为王,其他一切都是围绕它构建的。

在您的演示中,您正在列表之间移动项目。您正在更新模型并将 HTML 绑定到该模型。那里没有错 - 这是正确的方法并且有效。

这里增加的挑战是您还想移动表单组。我们仍然需要先考虑模型,但也要考虑在列表之间移动项目的同时移动相关状态。

抽象地说,你目前有

list1: [];
selected1: [];

list2: [];
selected2: [];

如果您想从 1 -> 2 移动项目,您的 move 方法会将任何选定的项目从items1to删除items2。简单的。

添加表单后,您将拥有如下结构:

list1: [];
selected1: [];
form1: FormGroup;
formArray1: FormArray;

list2: [];
selected2: [];
form2: FormGroup;
formArray2: FormArray;

当您从 1 -> 2 移动项目时,您将继续将项目从 移动list1list2,但现在您还需要从 中删除相关项目formArray1并将其添加到formArray2

我正在存储对表单数组的引用,以使它们以后更易于使用。

构建表单

使用表单数组可以说是这个答案中最复杂的部分。表单数组的关键在于 HTML 结构模仿了FormGroup您构建的对象的结构。

我们可以使用FormBuilder从数组构建表单并像这样绑定到它:

组件.ts

buildForm() {
  this.model = [ 
    { value: 'a' }, { value: 'b' }, { value: 'c' }
  ];

  // create a form group for each item in the model
  const formGroups = this.model.map(x => this.formBuilder.group({
    value: this.formBuilder.control(x.value)
  }));

  // create a form array for the groups
  const formArray = this.formBuilder.array(formGroups);

  // create the top-level form
  this.form = this.formBuilder.group({
    array: formArray
  });
}

并像这样在 HTML 中绑定到它:

<form [formGroup]="form1" (submit)="onSubmit()">
  <div formArrayName="array">
    <div *ngFor="let item of list1; let i = index" [formGroupName]="i">
      <input formControlName="value" />
    </div>
  </div>
  <button>Submit</button>
</form>

这将为数组中的每个项目生成一个输入,分别包含值“a”、“b”、“c”。

移动物品

在数组之间移动项目是一个简单的 JavaScript 问题。我们需要splice源数组和push目标数组。

要将项目从列表 1 移动到列表 2:

// move selected items from model 1
this.selected1.forEach(item => {
  const index = this.list1.indexOf(item);
  this.list1.splice(index, 1);
  this.list2.push(item);
});

this.selected1.length = 0;

这将遍历列表 1 中的每个选定项目,将其从列表中拼接,将其推送到列表 2。然后它将清除选定的项目;

移动表单组

您将在移动项目的同时移动表单组。它在概念上是相似的——你从一个中删除并添加到另一个。您从模型构建了表单数组,因此您知道索引匹配。

// move selected items from model 1
this.selected1.forEach(item => {
  const index = this.list1.indexOf(item);
  const formGroup: FormGroup = this.formArray1.controls[index] as FormGroup;

  this.list1.splice(index, 1);

  // move between form arrays
  this.formArray1.removeAt(index);
  this.formArray2.push(formGroup);

  this.list2.push(item);
});

请注意这里有 2 行在表单数组之间移动,看起来类似于用于在常规数组之间移动的 2 行。

formArray.removeAt(index)并且formArray.push(formGroup)正在搬家。与表单数组的不同之处在于我们需要先使用this.formArray1.controls[index] as FormGroup;.

演示:https ://stackblitz.com/edit/angular-3cwnsv

警告

在此设计中,从数组和表单中删除和添加的顺序很重要。您将 HTML 绑定到数组和表单。您通过遍历数组来创建输入数组,并将每个项目绑定到i表单数组中的第 th 组。如果您先从表单中删除,您现在将拥有n数组中的n - 1项目和表单数组中的项目。尝试绑定到未定义的n表单组时会出错。

您现在正在执行具有多个操作的事务。

除了确保以正确的顺序删除和添加之外,解决此问题的一种方法是使用OnPush更改检测。阅读此内容,因为除了最简单的应用程序之外,这对所有应用程序都是一个很好的策略。

下一步

为了回答的目的,我保持我的演示简单。就目前而言,它并不是特别可扩展或可重用的。有很多重复的代码和错误的命名来尝试避免被与您的应用程序相关的嵌套组件和属性名称分心。

实际上,您可能希望创建一个子组件来负责我复制的许多代码。其设计绝对超出了这个问题的范围。


推荐阅读