web-components
web-components copied to clipboard
[combo-box] Add option for auto-focusing first matching item [2 days]
Description
The vaadin-combo-box element is not selecting the filtered option after tabbing out of the field.
Expected outcome
The current value should be selected when tabbing out.
Actual outcome
The current value is not selected.
Live Demo
There is no live demo for this issue, sorry. However I recorded a short video showing the issue.
Steps to reproduce
- Put a
vaadin-combo-boxelement in the page. - Open the page in a web browser.
- Search for a valid option in the combo box but don't select this option.
- Tab out of the field.
Browsers Affected
- [X] Chrome (only browser I tested)
- [ ] Firefox
- [ ] Safari
- [ ] Edge
- [ ] IE 11
- [ ] iOS Safari
- [ ] Android Chrome
This would be a very useful feature for heavy data entry applications (not uncommon use for Vaadin), where speed is important. Having to press arrow-down and enter before tabbing to the next field might not sound like much, but the speed with which data entry users fill in forms can really make this a serious workflow bottleneck.
I would propose that this is provided as a setting on the ComboBox, since the described behavior might not always be desired.
Works for me. Would be nice to see if at least a code snippet to reproduce the issue.
Code is not relevant here -- we're referring to the default standard behavior of the CB, which obviously is not a bug, and should probably remain as the default behavior, but would benefit from an optional mode allowing for faster selection.
User action currently required to select item:
- Type into field to filter items
- Arrow-down to focus desired item
- Tab to blur field -> Focused item is selected
Desired optional mode to select an item:
- Type into field to filter until only one item is available
- Tab to blur field -> Only available item is selected
Alternately, this could even be:
- Type into field to filter items
- Tab to blur field -> First available item is selected
Type into field to filter until only one item is available
I see. Now it only gets selected once you entered all the characters. Otherwise, it isn't.
Proposal:
- Let's add an API to the combox called
autoFocusFirstMatch - When enabled, the topmost match is automatically focused when the filter text is changed and non-empty
- Contrary to manual focusing of list items (e.g. with arrow keys), the input field text is neither updated to match it, nor selected
- When
allowCustomValueis enabled, this the autofocus setting is ignored (i.e. default behavior is used).
Adding a simple workaround here that should enable the basic use case while waiting for the final implementation.
public class AutoComboBox<T> extends ComboBox<T> {
@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
this.getElement().getNode().runWhenAttached((ui) -> {
ui.beforeClientResponse(this, (context) -> {
ui.getPage().executeJs("$0.addEventListener('filter-changed', () => {setTimeout(() => {$0._focusedIndex = 0;});});", new Serializable[]{this.getElement()});
});
});
}
}
There is a component in the directory that mimics this behavior. Just for reference, the modifications over the original combobox for achieving this are in here.
Adding a simple workaround here that should enable the basic use case while waiting for the final implementation.
public class AutoComboBox<T> extends ComboBox<T> { @Override protected void onAttach(AttachEvent attachEvent) { super.onAttach(attachEvent); this.getElement().getNode().runWhenAttached((ui) -> { ui.beforeClientResponse(this, (context) -> { ui.getPage().executeJs("$0.addEventListener('filter-changed', () => {setTimeout(() => {$0._focusedIndex = 0;});});", new Serializable[]{this.getElement()}); }); }); } }
Some troubles with large data set. This works:
ComboBox<String> comboBox = new AutoComboBox<String>();
comboBox.setItems(Stream.generate(() -> RandomStringUtils.randomAlphabetic(10)).limit(10));
This not:
ComboBox<String> comboBox = new AutoComboBox<String>();
comboBox.setItems(Stream.generate(() -> RandomStringUtils.randomAlphabetic(10)).limit(1000));
If i add a second parameter 1000 to setTimeout, then it work, but with delays.
The issue is timeboxed to research if the solution is feasible. Automatic selection of the first item won't be a good idea, but autofocusing the first item should be considered. No item will be focused till the items are loaded. User would need to wait before proceeding to the next field. (in most cases that would be a matter of ms)
We implemented a workaround to focus the first item automatically, and our users love it
Contrary to manual focusing of list items (e.g. with arrow keys), the input field text is neither updated to match it, nor selected
Updating the input text value and selection to match can only work if starts-with filtering is used. But in that particular case, updating the input value to match and selecting the autocompleted part of it would be a nice visual confirmation that the first matching item will be selected when you tab out of the field.
There are two competing behavior proposals for this:
- Autoselect the first matching item
- Autoselect the only matching item if there is exactly one (see #9636)
I suppose the API for enabling this behavior could allow for selecting between these two, e.g. like this in Flow
setAutoSelect(AutoSelectBehavior.FIRST_MATCH);
setAutoSelect(AutoSelectBehavior.ONLY_MATCH);