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 :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.