【问题标题】:How to bind array of objects to formGroup and formarray using angular8如何使用角度 8 将对象数组绑定到 formGroup 和 formarray
【发布时间】:2020-06-07 04:13:58
【问题描述】:

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

提前致谢。

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

演示: DEMO 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>

【问题讨论】:

标签: angular angular-reactive-forms


【解决方案1】:

你的问题

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

设计

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

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

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

抽象地说,你目前有

list1: [];
selected1: [];

list2: [];
selected2: [];

如果您想从 1 -> 2 移动项目,您的移动方法会将所有选定的项目从 items1 删除到 items2。简单的。

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

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

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

并且当你从 1 -> 2 移动项目时,你将继续将项目从 list1 移动到 list2,但现在你还需要从 formArray1 中删除相关项目并将其添加到 @987654329 @。

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

构建表单

使用表单数组可以说是这个答案中最复杂的部分。表单数组的关键在于 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 绑定到数组和表单。您正在通过循环数组来创建输入数组,并将每个项目绑定到表单数组中的ith 组。如果您先从表单中删除,您现在将在数组中有n 项,在您的表单数组中有n - 1 项。尝试绑定到未定义的nth 表单组时会出错。

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

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

后续步骤

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

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

【讨论】:

  • 必须说这是一个高质量的答案。
  • 非常感谢,它就像一个魅力,我已经尝试了一个星期,非常感谢,你的回答对我来说就像是灵感,它促使我更多地了解这些主题。
  • @Bhrungarajni 你的任务并不简单——有很多活动部件。在这里了解技术上发生的事情显然很重要,但也要尝试用简单的术语来思考设计。如果您要为自己或其他任何人定义问题,那么将需求分解为简单的功能步骤也是必不可少的。祝你好运:)
  • @Bhrungarajni 我忘了将此添加到我的答案中。如果您没有使用 OnPush 更改检测,则移动项目的顺序很重要。我会解释为什么我要进行编辑
  • @KurtHamilton 当然,坦率地说,我对学习这些概念越来越感兴趣
猜你喜欢
  • 2019-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
相关资源
最近更新 更多