【问题标题】:how to use formsArray for multi select in an angular app如何在角度应用程序中使用 formsArray 进行多选
【发布时间】:2022-10-15 12:13:57
【问题描述】:

我有一个角度应用程序,在我的表单中,我有一个多选。多选值将存储在一个数组中,因此我使用的是 angular formsArray。

在我的 app.component.ts 中:

{{testForm.value|json}}

<form nz-form [formGroup]="testForm">
  <div>
    <p>Title</p>
    <nz-input formControlName="title"></nz-input>
  </div>

  <div>
    <p>Items</p>
    <nz-select
      [nzMode]="'multiple'"
      [nzPlaceHolder]="'Choose items'"
      formArrayName="items"
      [nzNotFoundContent]="'Item not found'"
    >
      <nz-option
        *ngFor="let item of items"
        [nzLabel]="item.title"
        [nzValue]="item.id"
      >
      </nz-option>
    </nz-select>
  </div>
</form>

在 .ts 文件中:

export class AppComponent {
  testForm: FormGroup;
  items = [
    {
      title: "Item 1",
      id: 1,
    },
    {
      title: "Item 2",
      id: 2,
    },
  ];

  constructor(private fb: FormBuilder) {
    this.testForm = this.fb.group({
      title: "",
      items: this.fb.array([]),
    });
  }
}

然而,问题是,即使我选择了多个项目,但我得到一个像这样的空数组:

{ "title": "test", "items": [] }

项目,属性未填充来自 nz-select 的值。我用这个例子创建了一个应用程序。链接在这里。

stackblitz app sample

【问题讨论】:

标签: angular


【解决方案1】:

拥有多个值并不意味着您必须使用 formArray。 只需将您的 html formArrayName="items" 更改为 formControlName="items"

<nz-select
  [nzMode]="'multiple'"
  [nzPlaceHolder]="'Choose items'"
  formControlName="items"
  [nzNotFoundContent]="'Item not found'"
>
  <nz-option
    *ngFor="let item of items"
    [nzLabel]="item.title"
    [nzValue]="item.id"
  >
  </nz-option>
</nz-select>

你的 ts 文件必须看起来像

this.testForm = this.fb.group({
      title: [''],
      items: [[]],
    });

【讨论】:

  • 感谢你的回答。但我仍然不确定为什么我不能在这里使用 formsArray,而创建 formsArray 是为了将值存储在数组中,对吧?以及您如何决定何时使用 fromsControl 以及何时使用 formsArray?我想将我的值存储在一个数组中,但你建议不要使用 formsArray。你是如何做出这个决定的?只是要求了解事实。 @folabiahn
  • FormArray 适用于控件数组(类似控件),而不是值数组。在这里,您的选择只是一个具有多个值的控件。想象一下,您有一个 TODO 列表,其中有一个按钮,每次在 TODO 列表中添加一个新项目。该新项目将是一个新控件(输入文本,您可能想检查其中的数据是否有效),这就是您要使用表单数组的地方。所以当你有多个控件(类似的控件)时使用formarray,你不知道控件的数量,你可以添加一个新的控件或者删除它......希望我的解释有帮助
【解决方案2】:

这是工作stackblitz

你可以做这样的HTML

<p>{{ orderForm.value | json }}</p>
<div [formGroup]="orderForm">
  <div
    formArrayName="items"
    *ngFor="let item of orderForm.get('items').controls; let i = index"
  >
    <div [formGroupName]="i">
      <input formControlName="title" placeholder="Item title" />
      <input formControlName="name" placeholder="Item name" />
    </div>
  </div>
</div>
<button (click)="addItem()">Add</button>

和脚本

import { Component, OnInit } from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  FormArray,
  FormControl,
  Validators,
} from '@angular/forms';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  title = 'formarray';
  orderForm!: FormGroup;
  items!: FormArray;
  constructor(private formBuilder: FormBuilder) {}
  ngOnInit() {
    this.orderForm = new FormGroup({
      items: new FormArray([]),
    });
  }
  createItem(): FormGroup {
    return this.formBuilder.group({
      title: '',
      name: '',
    });
  }
  addItem(): void {
    this.items = this.orderForm.get('items') as FormArray;
    this.items.push(this.createItem());
  }
}

【讨论】:

  • 我认为 OP 想要选择给定 items 数组中的一些项目,而不是创建新项目。
  • 谢谢@matthias-thalmann。但我想知道,为什么 formArray 不起作用?
  • @JDsmith formArray 在这种情况下没有多大意义。看看我或 FolabiAhn 的回答。一个普通的 formControl 可以解决问题
【解决方案3】:

在这种情况下,您不必使用 FormArray

在您的 HTML 中:

<form nz-form [formGroup]="testForm">
  <div>
    <p>Title</p>
    <nz-input formControlName="title"></nz-input>
  </div>

  <div>
    <p>Items</p>
    <nz-select
      [nzMode]="'multiple'"
      [nzPlaceHolder]="'Choose items'"
      formControlName="items" <!-- Use formControlName here -->
      [nzNotFoundContent]="'Item not found'"
    >
      <nz-option
        *ngFor="let item of items"
        [nzLabel]="item.title"
        [nzValue]="item.id"
      >
      </nz-option>
    </nz-select>
  </div>
</form>

在您的组件的打字稿中:

export class AppComponent {
  testForm: FormGroup;
  items = [
    {
      title: "Item 1",
      id: 1,
    },
    {
      title: "Item 2",
      id: 2,
    },
  ];

  constructor(private fb: FormBuilder) {
    this.testForm = this.fb.group({
      title: [""],
      items: [[]], // initialize as empty array
    });
  }
}

我在你的 StackBlitz-Link 上试过这个,它确实有效

【讨论】:

  • 您的回答很好,但项目的起始值将为空,因为您没有明确设置值。
  • @FolabiAhn 当然,你是对的!对上面的行感到困惑(我认为空数组是初始化)。我会更新我的答案。谢谢 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多