1

I have an angular app and in my form, I have a multi-select. Multiselect value will be stored in an array, therefore I am using angular formsArray.

in my 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>

and inside the .ts file:

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([]),
    });
  }
}

However, the problem is that, even though I selected the multiple items, but I am getting an empty array like that:

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

items, attribute is not filling up with the value from nz-select. I have created an app with this example. Here is the link.

stackblitz app sample

1

3 Answers 3

1

Having multiple values does not mean you have to use formArray. Just change in your html formArrayName="items" to 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>

And your ts file have to look like

this.testForm = this.fb.group({
      title: [''],
      items: [[]],
    });
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for the answer. but i am still not sure why i can't use formsArray here, whereas formsArray is created to store the value in an array, right? and how do you decide then when to use fromsControl and when to use formsArray? I want to store my values in an array, but u r suggesting not to use formsArray. How do you come up with that decision? just asking to learn the fact. @folabiahn
FormArray is suitable for an array of controls(similar controls), not arrays of values. Here your select is just one control with multiple values. Imagine you have a TODO list with a button to add each time a new item in the TODO list. That new item will be a new control(input text where maybe you want to check that the data in it is valid), that is where you are going to use a formarray. So use formarray when you have multiple controls (similar controls), you don't know the number of controls, you can add a new control ou remove it... Hope my explanation helps
0

Here is working stackblitz

you can do something like this 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>

And Script

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());
  }
}

3 Comments

I think OP wants to select some of the items in the given items array, and not create new items.
thank you @matthias-thalmann . But I wonder, why formArray is not working?
@JDsmith formArray does not make much sense in this case. Look at my or FolabiAhn's answer. A normal formControl does the trick
0

You do not have to use a FormArray in this case:

In your 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>

In your Component's Typescript:

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
    });
  }
}

I tried this on your StackBlitz-Link and it did work

2 Comments

you answer is good but the start value of items will be null since you are not explicitly setting the value.
@FolabiAhn of course, you are right! Got confused with the line above (I thought the empty array was the initialization). I'll update my answer. Thanks :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.