components
components copied to clipboard
Feature request: search/filter in select
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, 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
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).
This would be really useful, because currently md-select is veery poorly usable for long lists (e.g. country list) when compared to regular
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, it looks like it'll be possible soon: #7835
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.
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 ?
~~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
@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 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 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 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.
@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.
@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.
@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;
});
}
Thank you @macjohnny for your time.
@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 @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 thank for awesome code... it's helped me.
@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 thanks for your feedback. could you please move your issue to https://github.com/bithost-gmbh/ngx-mat-select-search/issues ?
This feature will be added to angular material2 ? Or stay in ngx-mat-select-search ?
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.
Is there an update?
Here is a simple implementation using mat-select:
https://stackblitz.com/edit/angular-material-mat-select-filter
@corinna000 What is the problem with previously mentioned implementation? Can you explain it?
@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 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.
(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).
Is there any update that when this feature will be available?
@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.