Reputation: 25
I have a material UI autocomplete component in a ReactJS application which I desire to have the following behavior:
I was able to make these behaviors individually. I handled the first behavior with an onKeyDown waiting for an enter key, and the second + third behavior with an onChange as suggested here: stackoverflow.com/questions/58666189/getting-the-value-in-the-react-material-ui-autocomplete.
The problem appears when I put both events together. When I attempt to scroll through the choices with arrow keys and press enter (behavior 2), both the onKeyDown and onChange events get fired. This fires BOTH event A with what the user typed and event B with what the user selected, when I only want to fire event B with what the user selected. Is there a way to detect if the user has begun scrolling through the autocomplete suggestions with arrow keys (so that I can wrap event A in an if condition), or an alternative way to look at this problem to resolve it?
The Autocomplete component:
<Autocomplete options={someArrayOfStrings}
onChange={this.submitComment} // event B
onKeyDown={this.submitCommentEnter} // event A
value={this.state.userInput} // what the user has typed
autoComplete
freeSolo
renderInput={(params) => <TextField {...params}
fullWidth
label="Search"
variant="outlined"/>}/>
Event A (submitCommentEnter):
submitCommentEnter(e) {
if (e.key == 'Enter') { // possibly add check if user is scrolling through autocomplete with arrow keys here?
/* content of event A here; uses this.state.userInput */
}
}
Event B (submitComment):
submitComment(event, value) {
if (value !== null) {
/* content of event B here; uses value */
}
}
Upvotes: 1
Views: 3614
Reputation: 1216
You don't need to handle the keyDown event, You just need to use the reason of on-change
event as per document onChange provide three params
onChange={(event, value, reason) => {
console.log("onChange", reason, value, event.currentTarget);
}}
The reason can be of 5 types "create-option", "select-option", "remove-option", "blur" or "clear"
. when you press enter in text field reason will be create-option
and when you select an option from the drop-down the reason will be select-options
, below is the complete code to verify the fact.
import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";
const someArrayOfStrings = ["test", "test2", "test3"];
export default function CheckboxesTags() {
const [selectedValues, setSelectedValues] = React.useState();
return (
<React.Fragment>
<Autocomplete
options={someArrayOfStrings}
onChange={(event, value, reason) => {
console.log("onChange", reason, value, event.currentTarget);
// setSelectedValues(value);
}}
value={selectedValues} // what the user has typed
autoComplete
freeSolo
renderInput={params => (
<TextField {...params} fullWidth label="Search" variant="outlined" />
)}
/>
</React.Fragment>
);
}
I have also created this code-sandbox project, where you can check the console for
Upvotes: 2