components icon indicating copy to clipboard operation
components copied to clipboard

Feature request: search/filter in select

Open xuanshenbo opened this issue 7 years ago • 66 comments

Bug, feature request, or proposal:

Feature request

What is the expected behavior?

User able to search/filter the options in a select

What is the current behavior?

User must scroll the select to find the desired option

What is the use-case or motivation for changing an existing behavior?

When there is a long list of options, it's not easy to find an option

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Latest Angular Material as of 12 July 2017

Is there anything else we should know?

This is different from autocomplete, autocomplete is a free-text input field.

I haven't found anything in Material Design related to this, but this could be an important feature

xuanshenbo avatar Jul 12 '17 03:07 xuanshenbo

@xuanshenbo, have you try a function to validate selection of the md-autocomplete at the (blur) event? I know it's not exactly the user experience that you're looking for, but I think it's a nice workaround: https://plnkr.co/edit/HzJNtcNLdctAbfeHbWCs?p=preview

julianobrasil avatar Jul 12 '17 10:07 julianobrasil

This is something we do plan on supporting eventually (similar to the md-select-header from AngularJS Material), but are still figuring out exactly how we want to implement it (the a11y is rather tricky).

jelbourn avatar Jul 13 '17 02:07 jelbourn

This would be really useful, because currently md-select is veery poorly usable for long lists (e.g. country list) when compared to regular

lightheaded avatar Aug 03 '17 14:08 lightheaded

Hey guys. Thanks for this great library of Material Components. Could you please add this feature in your roadmap? I believe it is important functionality, as most have already mentioned, and a must have in a long list. Also, it would be great if the filtering function could be defined by us (return true or false). @crisbeto @DevVersion @amcdnl @mmalerba @andrewseguin @jelbourn

nekkon avatar Oct 30 '17 09:10 nekkon

@nekkon, it looks like it'll be possible soon: #7835

julianobrasil avatar Oct 30 '17 09:10 julianobrasil

Indeed https://github.com/angular/material2/pull/7835 would be the way to implement search/filtering. @crisbeto is waiting for feedback before merging, so please give your feedback there if you have any.

jrood avatar Dec 06 '17 19:12 jrood

I have implemented this capability as a wrapper around mat-autocomplete - and as a base class that can easily be reused to make visual variations. Repository and demo link below.

https://github.com/OasisDigital/angular-material-obs-autocomplete

https://oasisdigital.github.io/angular-material-obs-autocomplete/

I am very interested in ideas in how I could reshape this work, in to the form of a component or similar thing to offer as a PR. Maybe the pair-of-functions that my solution uses, could be reshaped to something more like a mat-grid's DataSource ?

kylecordes avatar Dec 23 '17 01:12 kylecordes

~~Here is an implementation using mat-select: https://mat-select-search.stackblitz.io Code: https://stackblitz.com/edit/mat-select-search?file=app%2Fmat-select-search%2Fmat-select-search.component.ts~~

See https://github.com/bithost-gmbh/ngx-mat-select-search image

@jelbourn @crisbeto might this be worth filing as a PR once https://github.com/angular/material2/issues/2812 / https://github.com/angular/material2/pull/7835 is ready?

macjohnny avatar Feb 12 '18 11:02 macjohnny

@macjohnny this is great! However, it has a strange behavior when using the "multiple" attribute of the mat-select. When filtering and then selecting a value from the filtered list, it overrides and removes the previously selected values, which is not the desired behavior.

Other then that it's great!

eyalhakim avatar Feb 12 '18 17:02 eyalhakim

@eyalhakim Thanks for your feedback. I added an example with [multiple]=true and adapted the implementation of the mat-select-search to fix the behavior you described in https://github.com/angular/material2/issues/5697#issuecomment-365005477

when using the "multiple" attribute of the mat-select. When filtering and then selecting a value from the filtered list, it overrides and removes the previously selected values, which is not the desired behavior.

so now it should also work correctly with [multiple]=true

macjohnny avatar Feb 13 '18 09:02 macjohnny

@macjohnny works perfectly! thank you.

I would also suggest using <mat-icon>close</mat-icon> for clearing the filter.

Would appreciate if you release this as an npm package.

eyalhakim avatar Feb 13 '18 12:02 eyalhakim

@macjohnny Same here, I would be delighted to use your component if your release it as an NPM package while waiting for the official implementation by the Angular team.

kanidjar avatar Feb 20 '18 16:02 kanidjar

@macjohnny I am planning on using your mat-select-search component but I dont know how to use it to pre-select a value, for example, I already entered a value previously and when I try to show this component, I want to show the value preselected. I am able to filter the values, the dropdown shows only the filtered item but it doesnt show on the input unless I select the dropdown and select the value again. Any help would be much appreciated.

speddi avatar Feb 24 '18 18:02 speddi

@eyalhakim thanks for your feedback. I adapted the code to use <mat-icon>close</mat-icon> for clearing the filter as you suggested.

@eyalhakim @kevin-anidjar I will try to publish it as an npm package this week. ~~Meanwhile, you can simply copy the code of the https://stackblitz.com/edit/mat-select-search?file=app%2Fmat-select-search%2Fmat-select-search.component.ts file together with its html / scss into your application.~~ See https://github.com/bithost-gmbh/ngx-mat-select-search

@speddi due to the use of the async pipe in the example <mat-option *ngFor="let bank of filteredBanks | async">, the initial value needs to be set after the filteredBanks observable emits and hence after the mat-option elements are present, because it is only possible to set a value of the `MatSelect that is available among the current options:

  ngOnInit() {
    // set initial selection
    this.bankCtrl.setValue(this.banks[1]);
    ...
  }

  ngAfterViewInit() {
    this.setInitialValue();
  }

  /**
   * Sets the initial value after the filteredBanks are loaded initially
   */
  private setInitialValue() {
    this.filteredBanks
      .pipe(take(1), takeUntil(this._onDestroy))
      .subscribe(() => {          
        // setting the compareWith property to a comparison function 
        // triggers initializing the selection according to the initial value of 
        // the form control (i.e. _initializeSelection())
        // this needs to be done after the filteredBanks are loaded initially 
        // and after the mat-option elements are available
        this.singleSelect.compareWith = (a: Bank, b: Bank) => a.id === b.id;
      });
  }

macjohnny avatar Feb 26 '18 13:02 macjohnny

Thank you @macjohnny for your time.

speddi avatar Feb 26 '18 16:02 speddi

@macjohnny - would be useful to see this released formally with some sort of license. Can't really use it until then which is a shame as it's a solid looking implementation.

artparks avatar Feb 27 '18 19:02 artparks

@artparks @speddi @eyalhakim @kevin-anidjar I finally managed to bundle the code and publish it as an npm package:

npm install ngx-mat-select-search

See https://github.com/bithost-gmbh/ngx-mat-select-search for docs and issues / improvements. Contributions are welcome, and I would be glad if at some point we could have an official implementation in the material library.

See it in action at https://stackblitz.com/github/bithost-gmbh/ngx-mat-select-search-example

macjohnny avatar Feb 28 '18 19:02 macjohnny

@macjohnny thank for awesome code... it's helped me.

dreamid27 avatar Mar 07 '18 14:03 dreamid27

@macjohnny Such an awesome work! I saw @eyalhakim comment that there was a problem with the filtering for multi select and it was fixed. However there is one more case where it doesn't work - if initially I have all values selected for multi select and then I filter and after that deselect a value, then previously selected values are removed again.

An example is shown here: https://stackblitz.com/edit/github-g1zbuf?embed=1&file=src/app/app.component.html How to reproduce: Open multi select, type 'France', deselect one option (for example Bank C (France)) - the result is that all other previously selected values are removed.

Could you please check that case?

joqkey avatar Mar 17 '18 09:03 joqkey

@joqkey thanks for your feedback. could you please move your issue to https://github.com/bithost-gmbh/ngx-mat-select-search/issues ?

macjohnny avatar Mar 19 '18 06:03 macjohnny

This feature will be added to angular material2 ? Or stay in ngx-mat-select-search ?

WizardPC avatar Mar 29 '18 12:03 WizardPC

Here is how i handled it. I used mat-autocomplete instead of mat-select https://stackblitz.com/edit/angular-v1b716 I used two form controls. One for the autocomplete and one for multiple selection which I managed manually.

irinelpascu avatar May 15 '18 11:05 irinelpascu

Is there an update?

kelvinlouis avatar Jul 10 '18 14:07 kelvinlouis

Here is a simple implementation using mat-select: https://stackblitz.com/edit/angular-material-mat-select-filter screen shot 2018-07-13 at 16 47 21

yoheimiyamoto avatar Jul 13 '18 07:07 yoheimiyamoto

@corinna000 What is the problem with previously mentioned implementation? Can you explain it?

yoheimiyamoto avatar Aug 03 '18 01:08 yoheimiyamoto

@macjohnny thank you for this masterpiece, just what I was looking for.

I just found that the search fields has a bug when using special characters. If you type an special character, like 'é' it shows the 'noEntriesFoundLabel'. Is there a workaround?

I also found that when you delete in the search field with the "backspace" (keyCode === 8), and reach the last character the action history.back() of the browser is triggered. I solved it by adding this to the _handleKeydown method:

_handleKeydown(event: KeyboardEvent) {
    if (event.keyCode === 32) {
        // do not propagate spaces to MatSelect, as this would select the currently active option
        event.stopPropagation();
    }
    //Code that prevents the trigger of the history.back() browser action.
    if (event.keyCode === 8) {
        if (this._value.length <= 1) {
            event.preventDefault();
            this._reset();
            return false;
        }
    }
}

Again thank you and hope my solution helps improve the implementation

teoCasasbuenas avatar Aug 10 '18 20:08 teoCasasbuenas

@teoCasasbuenas would you mind creating a new issue here: https://github.com/bithost-gmbh/ngx-mat-select-search/issues ? also, it would be great if you could create a PR for your fix.

Update: the issue https://github.com/bithost-gmbh/ngx-mat-select-search/issues/49 could not be reproduced with the current version as it was only present in early versions.

macjohnny avatar Aug 14 '18 10:08 macjohnny

(I'm going through the highest voted issues today an commenting on their status)

So, this is a big one. We very much know that this feature is super in demand. We hear it from a lot of people inside Google, too. There's been a PR floating around for it for ages. The main problem has been getting a functional a11y interaction pattern for the feature. The select currently uses the role="listbox" pattern, which just does not play nicely with any kind of non-option content.

As of ARIA 1.1, though, there's a new pattern available; using role="combobox" along with a role="dialog" element (via aria-owns) seems like a viable path forward for this feature. The current plan is include the foundation for this interaction pattern as we rework the select components as part of integrating MDC Web into our library (see my recent ng-conf talk).

jelbourn avatar May 17 '19 23:05 jelbourn

Is there any update that when this feature will be available?

akvaliya avatar Jul 25 '19 09:07 akvaliya

@akvaliya not at this time. It's not currently a feature that is supported by MDCSelect.

Due to the difficulty of supporting this as part of mat-select in an accessible way, it may be better to create a separate community component that is focused on meeting this specific use case in an accessible way.

Splaktar avatar Jul 30 '19 00:07 Splaktar