I'm using Material UI (5) autocomplete to provide search functionality with the following user scenarios:
First first scenario doesn't work. The second does. Does autocomplete have its own ability to handle the enter key press or do I need to wrap it to get that key press event and send text input to search?
Because the first scenario has to be solved, I added a submit button. If I wrap the autocomplete in a div and put the action on that, the state doesn't have the correct query value.
I would like the autocomplete to send the correct text (either input or selected from suggestions) when the enter button is pressed.
I've tried freesolo and not freesolo and it doesn't seem to change the outcome. Does it only work in combination with another configuration?
import React, { useState, useEffect } from 'react';
import { TextField, Autocomplete, Button, Box } from '@mui/material';
import axios from '../../axios.js';
export default function SearchBar2({ postSearchHandler, query }) {
const [q, setQ] = useState(() => query || '');
const [suggestions, setSuggestions] = useState([]);
const search = (value) => {
console.log(`search: ${value}`);
postSearchHandler(value);
};
useEffect(() => {
console.log(`useEffect getSuggestions: ${q}`);
if (q) {
axios.post('/api/suggest', { q, top: 5, suggester: 'sg' })
.then(response => {
setSuggestions(response.data.suggestions.map(s => s.text));
}).catch (error =>{
console.log(error);
setSuggestions([]);
});
}}, [q]);
const onInputChangeHandler = (event, value) => {
console.log(`onInputChangeHandler: ${value}`);
setQ(value);
};
const onChangeHandler = (event, value) => {
console.log(`onChangeHandler: ${value}`);
setQ(value);
search(value);
};
const onEnterButton = (event) => {
console.log(`onEnterButton: ${q}`);
// if enter key is pressed
if (event.key === 'Enter') {
search(q);
}
};
return (
<div
className="input-group"
style={{ width: '95%', display: 'flex', justifyContent: 'center', alignItems: 'center', margin: '0 auto' }}
>
<Box sx={{ display: 'flex', alignItems: 'center', width: '75%', minWidth: '390px' }}>
<Autocomplete
freeSolo
value={q}
options={suggestions}
onInputChange={onInputChangeHandler}
onChange={onChangeHandler}
disableClearable
sx={{
width: '75%',
'& .MuiAutocomplete-endAdornment': {
display: 'none'
}
}}
renderInput={(params) => (
<TextField
{...params}
id="search-box"
className="form-control rounded-0"
placeholder="What are you looking for?"
onBlur={() => setSuggestions([])}
onClick={() => setSuggestions([])}
/>
)}
/>
<div className="input-group-btn" style={{ marginLeft: '10px' }}>
<Button variant="contained" color="primary" onClick={() => {
console.log(`search button: ${q}`);
search(q)}
}>
Search
</Button>
</div>
</Box>
</div>
);
}
I'm using Material UI (5) autocomplete to provide search functionality with the following user scenarios:
First first scenario doesn't work. The second does. Does autocomplete have its own ability to handle the enter key press or do I need to wrap it to get that key press event and send text input to search?
Because the first scenario has to be solved, I added a submit button. If I wrap the autocomplete in a div and put the action on that, the state doesn't have the correct query value.
I would like the autocomplete to send the correct text (either input or selected from suggestions) when the enter button is pressed.
I've tried freesolo and not freesolo and it doesn't seem to change the outcome. Does it only work in combination with another configuration?
import React, { useState, useEffect } from 'react';
import { TextField, Autocomplete, Button, Box } from '@mui/material';
import axios from '../../axios.js';
export default function SearchBar2({ postSearchHandler, query }) {
const [q, setQ] = useState(() => query || '');
const [suggestions, setSuggestions] = useState([]);
const search = (value) => {
console.log(`search: ${value}`);
postSearchHandler(value);
};
useEffect(() => {
console.log(`useEffect getSuggestions: ${q}`);
if (q) {
axios.post('/api/suggest', { q, top: 5, suggester: 'sg' })
.then(response => {
setSuggestions(response.data.suggestions.map(s => s.text));
}).catch (error =>{
console.log(error);
setSuggestions([]);
});
}}, [q]);
const onInputChangeHandler = (event, value) => {
console.log(`onInputChangeHandler: ${value}`);
setQ(value);
};
const onChangeHandler = (event, value) => {
console.log(`onChangeHandler: ${value}`);
setQ(value);
search(value);
};
const onEnterButton = (event) => {
console.log(`onEnterButton: ${q}`);
// if enter key is pressed
if (event.key === 'Enter') {
search(q);
}
};
return (
<div
className="input-group"
style={{ width: '95%', display: 'flex', justifyContent: 'center', alignItems: 'center', margin: '0 auto' }}
>
<Box sx={{ display: 'flex', alignItems: 'center', width: '75%', minWidth: '390px' }}>
<Autocomplete
freeSolo
value={q}
options={suggestions}
onInputChange={onInputChangeHandler}
onChange={onChangeHandler}
disableClearable
sx={{
width: '75%',
'& .MuiAutocomplete-endAdornment': {
display: 'none'
}
}}
renderInput={(params) => (
<TextField
{...params}
id="search-box"
className="form-control rounded-0"
placeholder="What are you looking for?"
onBlur={() => setSuggestions([])}
onClick={() => setSuggestions([])}
/>
)}
/>
<div className="input-group-btn" style={{ marginLeft: '10px' }}>
<Button variant="contained" color="primary" onClick={() => {
console.log(`search button: ${q}`);
search(q)}
}>
Search
</Button>
</div>
</Box>
</div>
);
}
So you want to handle this situation:
User enters a text and presses Enter without selecting an option from dropdown list
To do this you need to implement the onKeyDown
event.
onKeyDown={(event) => {
if (event.key === 'Enter') {
console.log(`onEnterButton: ${q}`);
search(q);
}
}}
Full code:
<Autocomplete
freeSolo
value={q}
options={suggestions}
onInputChange={onInputChangeHandler}
onChange={onChangeHandler}
disableClearable
sx={{
width: '75%',
'& .MuiAutocomplete-endAdornment': {
display: 'none',
},
}}
onKeyDown={(event) => {
if (event.key === 'Enter') {
console.log(`onEnterButton: ${q}`);
search(q);
}
}}
renderInput={(params) => (
<TextField
{...params}
id="search-box"
className="form-control rounded-0"
placeholder="What are you looking for?"
onBlur={() => setSuggestions([])}
onClick={() => setSuggestions([])}
/>
)}
/>
Docs Reference.