最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

angular - How to use PrimeNG Autocomplete with multiple selection in a FormArray? - Stack Overflow

programmeradmin1浏览0评论

I'm working on an Angular project where I need to implement a form that includes a FormArray with multiple FormControl instances, each using PrimeNG's Autocomplete component with multiple selection enabled. I'm having trouble figuring out how to bind the selected values from the Autocomplete component to the FormArray.

Here's a simplified version of what I'm trying to achieve:

I have a FormArray that dynamically generates a list of FormControl instances.

Each FormControl should be associated with a PrimeNG Autocomplete component that allows multiple selections.

When the user selects multiple items from the Autocomplete, those selected items should be stored in the corresponding FormControl.

Here's a snippet of my current setup:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';

@Component({
  selector: 'app-my-form',
  templateUrl: './my-formponent.html',
  styleUrls: ['./my-formponent.css']
})
export class MyFormComponent implements OnInit {
  myForm: FormGroup;
  suggestions: any[] = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      items: this.fb.array([this.createItem()])
    });
  }

  createItem(): FormGroup {
    return this.fb.group({
      selectedItems: new FormControl([])
    });
  }

  get items(): FormArray {
    return this.myForm.get('items') as FormArray;
  }

  addItem() {
    this.items.push(this.createItem());
  }

  removeItem(index: number) {
    this.items.removeAt(index);
  }
}

And the corresponding HTML:

<form [formGroup]="myForm">
  <div formArrayName="items">
    <div *ngFor="let item of items.controls; let i = index" [formGroupName]="i">
      <p-autoComplete 
        formControlName="selectedItems"
        [suggestions]="suggestions"
        [multiple]="true"
        (completeMethod)="filterSuggestions($event)"
        field="name">
      </p-autoComplete>
    </div>
  </div>
  <button type="button" (click)="addItem()">Add Item</button>
</form>
  1. How do I properly bind the selected values from the PrimeNG Autocomplete component to the FormControl within the FormArray?

  2. Is there a specific way to handle the completeMethod to filter suggestions dynamically for each FormControl in the FormArray?

  3. Are there any common pitfalls or best practices when using PrimeNG Autocomplete with Angular's reactive forms, especially with FormArray?

Any help or guidance would be greatly appreciated! Thanks in advance.

I'm working on an Angular project where I need to implement a form that includes a FormArray with multiple FormControl instances, each using PrimeNG's Autocomplete component with multiple selection enabled. I'm having trouble figuring out how to bind the selected values from the Autocomplete component to the FormArray.

Here's a simplified version of what I'm trying to achieve:

I have a FormArray that dynamically generates a list of FormControl instances.

Each FormControl should be associated with a PrimeNG Autocomplete component that allows multiple selections.

When the user selects multiple items from the Autocomplete, those selected items should be stored in the corresponding FormControl.

Here's a snippet of my current setup:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';

@Component({
  selector: 'app-my-form',
  templateUrl: './my-form.component.html',
  styleUrls: ['./my-form.component.css']
})
export class MyFormComponent implements OnInit {
  myForm: FormGroup;
  suggestions: any[] = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      items: this.fb.array([this.createItem()])
    });
  }

  createItem(): FormGroup {
    return this.fb.group({
      selectedItems: new FormControl([])
    });
  }

  get items(): FormArray {
    return this.myForm.get('items') as FormArray;
  }

  addItem() {
    this.items.push(this.createItem());
  }

  removeItem(index: number) {
    this.items.removeAt(index);
  }
}

And the corresponding HTML:

<form [formGroup]="myForm">
  <div formArrayName="items">
    <div *ngFor="let item of items.controls; let i = index" [formGroupName]="i">
      <p-autoComplete 
        formControlName="selectedItems"
        [suggestions]="suggestions"
        [multiple]="true"
        (completeMethod)="filterSuggestions($event)"
        field="name">
      </p-autoComplete>
    </div>
  </div>
  <button type="button" (click)="addItem()">Add Item</button>
</form>
  1. How do I properly bind the selected values from the PrimeNG Autocomplete component to the FormControl within the FormArray?

  2. Is there a specific way to handle the completeMethod to filter suggestions dynamically for each FormControl in the FormArray?

  3. Are there any common pitfalls or best practices when using PrimeNG Autocomplete with Angular's reactive forms, especially with FormArray?

Any help or guidance would be greatly appreciated! Thanks in advance.

Share Improve this question asked 2 days ago syahiruddinsyahiruddin 5168 silver badges23 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0
  1. You can remove field property this is meant to be used only when you are using an array of objects for the dropdown [{id: 1, name: 'apple'}].

     <p-autoComplete
       formControlName="selectedItems"
       [suggestions]="suggestions"
       [multiple]="true"
       (completeMethod)="search($event)"
     >
     </p-autoComplete>
    
  2. You should maintain two copies of the dropdown object, one for storing the original values and another you use to show the filtered values from the input typed by the user.

     suggestions: any[] = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
     suggestionsBackup: any[] = [
         'Apple',
         'Banana',
         'Cherry',
         'Date',
         'Elderberry',
     ];
     ...
    
     ...
     search(event: AutoCompleteCompleteEvent) {
         this.suggestions = this.suggestionsBackup.filter((item: string) =>
         item.toLowerCase().includes(event.query.toLowerCase())
         );
     }
    

Apart from this all seems good, you might want to use the new angular control flow which needs zero imports.

Full Code:

HTML:

    <form [formGroup]="myForm">
    <div formArrayName="items">
        @for(item of items.controls; let i = $index;track i) {
            <div [formGroupName]="i">
            <p-autoComplete
                formControlName="selectedItems"
                [suggestions]="suggestions"
                [multiple]="true"
                (completeMethod)="search($event)"
            >
            </p-autoComplete>
            </div>
        }
    </div>
    <button type="button" (click)="addItem()">Add Item</button>
    </form>

    <div>{{myForm.value | json}}</div>

TS:

import { Component } from '@angular/core';
import { ImportsModule } from './imports';
import { AutoComplete } from 'primeng/autocomplete';
import { FormGroup, FormBuilder, FormControl, FormArray } from '@angular/forms';

interface AutoCompleteCompleteEvent {
  originalEvent: Event;
  query: string;
}

@Component({
  selector: 'autocomplete-basic-demo',
  templateUrl: './autocomplete-basic-demo.html',
  imports: [ImportsModule],
  standalone: true,
})
export class AutocompleteBasicDemo {
  myForm: FormGroup;
  suggestions: any[] = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
  suggestionsBackup: any[] = [
    'Apple',
    'Banana',
    'Cherry',
    'Date',
    'Elderberry',
  ];

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.myForm = this.fb.group({
      items: this.fb.array([this.createItem()]),
    });
  }

  createItem(): FormGroup {
    return this.fb.group({
      selectedItems: new FormControl([]),
    });
  }

  get items(): FormArray {
    return this.myForm.get('items') as FormArray;
  }

  addItem() {
    this.items.push(this.createItem());
  }

  removeItem(index: number) {
    this.items.removeAt(index);
  }

  search(event: AutoCompleteCompleteEvent) {
    this.suggestions = this.suggestionsBackup.filter((item: string) =>
      item.toLowerCase().includes(event.query.toLowerCase())
    );
  }
}

Stackblitz Demo

发布评论

评论列表(0)

  1. 暂无评论