downshift version: 4.0.7node version: 12.3.1npm (or yarn) version: yarn 1.21.1Reproduction repository:
https://codesandbox.io/s/downshift-examples-xgk4r?fontsize=14
(navigate to the typeahead example)
Problem description:
defaultHighlightIndex={0} is useful for allowing users to quickly select the first suggestion in a typeahead just by pressing enter. However, we found that it has an unfortunate side-effect of preventing form submission on enter when there are no items in the suggestions list (i.e. when the user is trying to enter something that's not part of the suggestions list).
Here's a slightly modified version of the typeahead example that changes the outer div to a form with a submit handler to help demonstrate the issue:
https://codesandbox.io/s/downshift-examples-xgk4r?fontsize=14
defaultHighlightedIndex={0} and typing in 123 (or anything else that causes the suggestions list to become empty) and then pressing enter. You'll see the "not-submitted" text at the top of the page turn into "submitted", which is triggered by the custom onSubmit handler on the form.defaultHighlightedIndex={0} back in and doing the same. You'll see that not-submitted remains unchanged, meaning the onSubmit was never called.Suggested solution:
I opened a PR a while ago that has a solution to this, but there are some outstanding issues with the tests, and I ended up finding a conflicting test case and am unsure how to move forward: https://github.com/downshift-js/downshift/pull/745
Would love to hear some thoughts on how this should be resolved. Thanks!
I will take a look, see if we can solve this out. Right now I am busy with some refactoring, will come back to it in a few days. Thanks!
We are not unsetting highlightedIndex when the items are empty. You can do that manually when items.length is 0 you can setHighlightedIndex to null or -1 so it does hit our handler. We have a preventDefault if Enter action is executed.
Enter(event) {
const {isOpen, highlightedIndex} = this.getState()
if (isOpen && highlightedIndex != null) {
event.preventDefault()
const item = this.items[highlightedIndex]
const itemNode = this.getItemNodeFromIndex(highlightedIndex)
if (item == null || (itemNode && itemNode.hasAttribute('disabled'))) {
return
}
this.selectHighlightedItem({
type: stateChangeTypes.keyDownEnter,
})
}
},
Most helpful comment
I will take a look, see if we can solve this out. Right now I am busy with some refactoring, will come back to it in a few days. Thanks!