Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make a multiselection in Autocomplete (Angular4+)?

Tags:

I want to make a multi selection on filtered items by the auto complete. Inspired from the following tutorial I tried this code:

The component :

 <form class="example-form">   <mat-form-field class="example-full-width">     <input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [matAutocomplete]="auto">     <mat-autocomplete #auto="matAutocomplete">       <mat-option *ngFor="let option of filteredOptions | async" [value]="option" multiple>       <mat-checkbox>         {{ option }}      </mat-checkbox>       </mat-option>     </mat-autocomplete>   </mat-form-field> </form> 

I added tag to enable selection but it does not work. Once I filter and select one option the menu closes and the checkbox doesn't even get checked. Is there a way to make a multiselection in Autocomplete? Thank you !!

like image 855
nour Avatar asked Mar 06 '18 12:03

nour


People also ask

How do I implement autocomplete in a mat select component?

Simple autocompleteStart by creating the autocomplete panel and the options displayed inside it. Each option should be defined by a mat-option tag. Set each option's value property to whatever you'd like the value of the text input to be when that option is selected.

What is the use of mat autocomplete?

The <mat-autocomplete>, an Angular Directive, is used as a special input control with an inbuilt dropdown to show all possible matches to a custom query.


1 Answers

Angular Material documentation for chips includes a nice example of how to get started with a multiple selection autocomplete:

<mat-form-field class="example-chip-list">   <mat-chip-list #chipList>     <mat-chip       *ngFor="let fruit of fruits"       [selectable]="selectable"       [removable]="removable"       (removed)="remove(fruit)">       {{fruit}}       <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>     </mat-chip>     <input       placeholder="New fruit..."       #fruitInput       [formControl]="fruitCtrl"       [matAutocomplete]="auto"       [matChipInputFor]="chipList"       [matChipInputSeparatorKeyCodes]="separatorKeysCodes"       [matChipInputAddOnBlur]="addOnBlur"       (matChipInputTokenEnd)="add($event)">   </mat-chip-list>   <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">     <mat-option *ngFor="let fruit of filteredFruits | async" [value]="fruit">       {{fruit}}     </mat-option>   </mat-autocomplete> </mat-form-field> 

Basically, you have a chip list bound to a list and an text input that allows to search within an autocomplete list.

import {COMMA, ENTER} from '@angular/cdk/keycodes'; import {Component, ElementRef, ViewChild} from '@angular/core'; import {FormControl} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatChipInputEvent} from '@angular/material'; import {Observable} from 'rxjs'; import {map, startWith} from 'rxjs/operators';  /**  * @title Chips Autocomplete  */ @Component({   selector: 'chips-autocomplete-example',   templateUrl: 'chips-autocomplete-example.html',   styleUrls: ['chips-autocomplete-example.css'], }) export class ChipsAutocompleteExample {   visible = true;   selectable = true;   removable = true;   addOnBlur = false;   separatorKeysCodes: number[] = [ENTER, COMMA];   fruitCtrl = new FormControl();   filteredFruits: Observable<string[]>;   fruits: string[] = ['Lemon'];   allFruits: string[] = ['Apple', 'Lemon', 'Lime', 'Orange', 'Strawberry'];    @ViewChild('fruitInput') fruitInput: ElementRef;    constructor() {     this.filteredFruits = this.fruitCtrl.valueChanges.pipe(         startWith(null),         map((fruit: string | null) => fruit ? this._filter(fruit) : this.allFruits.slice()));   }    add(event: MatChipInputEvent): void {     const input = event.input;     const value = event.value;      // Add our fruit     if ((value || '').trim()) {       this.fruits.push(value.trim());     }      // Reset the input value     if (input) {       input.value = '';     }      this.fruitCtrl.setValue(null);   }    remove(fruit: string): void {     const index = this.fruits.indexOf(fruit);      if (index >= 0) {       this.fruits.splice(index, 1);     }   }    selected(event: MatAutocompleteSelectedEvent): void {     this.fruits.push(event.option.viewValue);     this.fruitInput.nativeElement.value = '';     this.fruitCtrl.setValue(null);   }    private _filter(value: string): string[] {     const filterValue = value.toLowerCase();      return this.allFruits.filter(fruit => fruit.toLowerCase().indexOf(filterValue) === 0);   } } 

The code is pretty straightforward (filter based on text input after each typed character, remove an item from the list etc.). Of course, this should be tweaked to your needs (e.g. once you select an item, it should be filtered out for next autocomplete results).

like image 164
Alexei - check Codidact Avatar answered Sep 19 '22 18:09

Alexei - check Codidact