Another attempt at fixing autosuggest behavior

This commit is contained in:
Rainer Simon 2020-10-13 14:04:11 +02:00
parent e44f404e28
commit 75feeb2959
1 changed files with 86 additions and 72 deletions

View File

@ -1,83 +1,97 @@
import React, { useState } from 'react' import React, { Component, createRef } from 'react'
import { useCombobox } from 'downshift' import { useCombobox } from 'downshift'
const Autocomplete = props => { export default class Autocomplete extends Component {
const [ inputItems, setInputItems ] = useState(props.vocabulary); constructor(props) {
super(props);
const onInputValueChange = ({ inputValue }) => { this.element = createRef();
this.state = {
inputItems: props.vocabulary || []
}
}
componentDidMount() {
if (this.props.initialValue && this.element.current)
this.element.current.querySelector('input').value = this.props.initialValue;
}
onInputValueChange = ({ inputValue }) => {
if (inputValue.length > 0) { if (inputValue.length > 0) {
const prefixMatches = props.vocabulary.filter(item => { const prefixMatches = this.props.vocabulary.filter(item => {
return item.toLowerCase().startsWith(inputValue.toLowerCase()); return item.toLowerCase().startsWith(inputValue.toLowerCase());
}); });
setInputItems(prefixMatches); this.setState({ inputItems: prefixMatches });
} else { } else {
// ...or none, if the input is empty // ...or none, if the input is empty
setInputItems([]); this.setState({ inputItems: [] });
} }
} }
const { render() {
isOpen,
getMenuProps, const {
getInputProps, isOpen,
getComboboxProps, getMenuProps,
highlightedIndex, getInputProps,
getItemProps, getComboboxProps,
setInputValue highlightedIndex,
} = useCombobox({ getItemProps,
items: inputItems, setInputValue
onInputValueChange, } = useCombobox({
onSelectedItemChange: ({ inputValue }) => { items: this.state.inputItems,
onSubmit(inputValue); onInputValueChange: this.onInputValueChange,
onSelectedItemChange: ({ inputValue }) => {
onSubmit(inputValue);
setInputValue('');
}
});
const onSubmit = inputValue => {
setInputValue(''); setInputValue('');
if (inputValue.trim().length > 0)
this.props.onSubmit(inputValue);
} }
});
const onSubmit = inputValue => { const onKeyUp = evt => {
setInputValue(''); const { value } = evt.target;
if (inputValue.trim().length > 0)
props.onSubmit(inputValue);
}
const onKeyUp = evt => { if (evt.which == 13 && highlightedIndex == -1) {
const { value } = evt.target; onSubmit(value);
} else if (evt.which == 40 && value.length == 0) {
if (evt.which == 13 && highlightedIndex == -1) { setInputItems(this.props.vocabulary); // Show all options on key down
onSubmit(value); } else if (evt.which == 27) {
} else if (evt.which == 40 && value.length == 0) { this.props.onCancel && this.props.onCancel();
setInputItems(props.vocabulary); // Show all options on key down } else {
} else if (evt.which == 27) { this.props.onChange && this.props.onChange(value);
props.onCancel && props.onCancel(); }
} else {
props.onChange && props.onChange(value);
} }
}
return ( return (
<div className="r6o-autocomplete"> <div className="r6o-autocomplete" ref={this.element}>
<div {...getComboboxProps()}> <div {...getComboboxProps()}>
<input <input
{...getInputProps({ onKeyUp })} {...getInputProps({ onKeyUp })}
placeholder={props.placeholder} /> placeholder={this.props.placeholder} />
</div>
<ul {...getMenuProps()}>
{isOpen && this.state.inputItems.map((item, index) => (
<li style={
highlightedIndex === index
? { backgroundColor: '#bde4ff' }
: {}
}
key={`${item}${index}`}
{...getItemProps({ item, index })}>
{item}
</li>
))}
</ul>
</div> </div>
<ul {...getMenuProps()}> )
{isOpen && inputItems.map((item, index) => ( }
<li style={
highlightedIndex === index
? { backgroundColor: '#bde4ff' }
: {}
}
key={`${item}${index}`}
{...getItemProps({ item, index })}>
{item}
</li>
))}
</ul>
</div>
)
} }
export default Autocomplete;