I am trying to put buttons ("Accept" and "Cancel") under MUI Autocomplete element and am trying to implement the following
This is done by passing sx
to ListboxProps
I was trying various options to put the buttons within Autocomplete (in Paper, Popper, etc.), but with little luck.
Here is the simplified code:
import "./styles.css";
import { Autocomplete } from "@mui/lab";
import TextField from "@mui/material/TextField";
import Paper from "@mui/material/Paper";
import Box from "@mui/material/Box";
import Chip from "@mui/material/Chip";
export default function App() {
return (
<div className="App">
<Paper sx={{ padding: 1 }}>
<Autocomplete
freeSolo
options={["one", "two", "three", "four"]}
renderInput={(params) => <TextField {...params} />}
ListboxProps={{ sx: { height: 100 } }}
/>
<Box sx={{ display: "flex", direction: "row" }}>
<Chip label="Accept" sx={{ margin: 1 }} />
<Chip label="Cancel" sx={{ margin: 1 }} />
</Box>
</Paper>
</div>
);
}
Any help is greatly appreciated!
The PaperComponent
prop controls the Paper
element that surrounds the Autocomplete's list box. You can put additional content around that list box by customizing that Paper
component. The example below uses your original code for displaying the buttons when the list box is closed and then CustomPaper
takes care of displaying them when the list box is open. To manage the rendering of the buttons in one place, the buttons are passed as a prop to the custom Paper. In order for the buttons in CustomPaper
to be clickable, you need to call event.preventDefault()
in the onMouseDown
event; this prevents the blur event of the text input from occurring which would then trigger the closing of the list box. This same approach is used within Autocomplete
here and here.
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
import Paper from "@mui/material/Paper";
import Box from "@mui/material/Box";
import Chip from "@mui/material/Chip";
function CustomPaper({ children, buttons, ...other }) {
return (
<Paper {...other}>
{children}
{buttons}
</Paper>
);
}
export default function App() {
const buttons = (
<Box sx={{ display: "flex", direction: "row" }}>
<Chip
label="Accept"
sx={{ margin: 1 }}
onMouseDown={(event) => {
// Prevent input blur which triggers closing the Popper
event.preventDefault();
}}
onClick={() => console.log("Accept clicked")}
/>
<Chip
label="Cancel"
sx={{ margin: 1 }}
onMouseDown={(event) => {
// Prevent input blur which triggers closing the Popper
event.preventDefault();
}}
onClick={() => console.log("Cancel clicked")}
/>
</Box>
);
return (
<div className="App">
<Paper sx={{ padding: 1 }}>
<Autocomplete
freeSolo
options={["one", "two", "three", "four"]}
renderInput={(params) => <TextField {...params} />}
ListboxProps={{ sx: { maxHeight: 100 } }}
PaperComponent={CustomPaper}
componentsProps={{ paper: { buttons: buttons } }}
/>
{buttons}
</Paper>
</div>
);
}
Related answers: