components icon indicating copy to clipboard operation
components copied to clipboard

feat(autocomplete): Multiselect (chips input)

Open infacto opened this issue 3 years ago • 1 comments

Feature Description

Ability to select multiple entries from autocomplete. https://material.angular.io/components/autocomplete/overview

Use Case

For example when using with chips. multi-chip-select

Btw. it would be also nice if the chip select does not wrap and scroll horizontal instead or truncate (overflow hidden) with annotation of count of additional chips like (Chip 1) (Chip 2) +3 (means 5 chips, 2 visible, 3 hidden to prevent wrapping / changing height of input). Not tested but mabye the autocomplete select position may not updated when the input height is change while the overlay (list) is displayed.

Update: Ok this can be achieved by adding mat-checkbox to the options. So this feature request is maybe more about to add an example to the docs. Or what do you mean? It's maybe not that easy. The checkbox checked state must be synced with the selected chips. Also prevent closing autocomplete by click. preventDefault or stopPropagation doesn't work. etc.

https://material.angular.io/components/chips/examples

Update: Another quick solution would be to just keep the autocomplete list overlay open while click on items to add to the chip list.

Update: Here is an example. It's not from me, it's forked and might be polished. Just for inpriation. For example you need a div inside the option with click event to prevent close (stopPropagation/preventDefault). We can optimize this and add it to the examples. But since this is a little bit "hackish" we should consider to officially support this. Or give options to prevent close etc. I would not use a wrapper object for selected property. I would just bind checked to a method to check if value array includes item. And pointer-events none for the mat-checkbox (toggle only by option itself).

infacto avatar Nov 17 '22 12:11 infacto

I found a solution:

my.component.html

<mat-option class="checkbox-option">
  <div (click)="toggle($event, option)">
    <mat-checkbox [checked]="optionSelected(option)">{{ name }}</mat-checkbox>
  </div>
</mat-option>

The div is required to prevent autocomplete from closing.

my.component.ts

class MyComponent {
  selectedOptions = [];

  toggle(event, option) {
    event.stopPropagation();
    this.selectedOptions.push(option);
  }

  optionSelected(option) {
    this.selectedOptions.includes(option);
  }
}

We do not wrap options in { value, selected } as many other example in web shows. Instead we just add selected options to an array and check if option exist in array. But both solutions will work. ...

my.component.scss

.checkbox-option {
  user-select: none;
  mat-checkbox {
    pointer-events: none;
  }
}

We disable user-select to prevent selected text when e.g. clicked to fast (text will select on double click). We also disable pointer-events on mat-checkbox, because we only want to toggle the state from option.

You see this is a bit hackish. But it works well. Consider to support this out of the box. It's just a suggestion.

infacto avatar Nov 21 '22 14:11 infacto