I am integrating a multi-select using Material ui, this is what in my .tsx file
import React, { ReactNode } from "react";
import {
Streamlit,
StreamlitComponentBase,
withStreamlitConnection,
} from "streamlit-component-lib";
import FormControl from "@mui/material/FormControl";
import InputLabel from "@mui/material/InputLabel";
import MenuItem from "@mui/material/MenuItem";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import Checkbox from "@mui/material/Checkbox";
import ListItemText from "@mui/material/ListItemText";
import OutlinedInput from "@mui/material/OutlinedInput";
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 250,
},
},
};
interface MultiSelectComponentState {
selectedItems: string[];
}
class MultiSelectComponent extends StreamlitComponentBase {
state: MultiSelectComponentState = {
selectedItems: [],
};
handleChange = (event: SelectChangeEvent<typeof this.state.selectedItems>) => {
const {
target: { value },
} = event;
const names = this.props.args["options"]; // Assuming options are passed from Streamlit
if (value[value.length - 1] === 'all') {
const isAllSelected = names.length > 0 && this.state.selectedItems.length === names.length;
this.setState({
selectedItems: isAllSelected ? [] : names,
}, () => {
Streamlit.setComponentValue(this.state.selectedItems);
});
} else {
this.setState({
selectedItems: typeof value === "string" ? value.split(",") : value,
}, () => {
Streamlit.setComponentValue(this.state.selectedItems);
});
}
};
render = (): ReactNode => {
const names = this.props.args["options"]; // Assuming options are passed from Streamlit
const isAllSelected = names.length > 0 && this.state.selectedItems.length === names.length;
return (
<FormControl sx={{mt:5, m: 1, width: 300, height: 250, overflowY: "auto"}}>
<InputLabel id="multi-select-label">Select Items</InputLabel>
<Select
labelId="multi-select-label"
multiple
value={this.state.selectedItems}
onChange={this.handleChange}
input={<OutlinedInput label="Select Items" />}
MenuProps={MenuProps}
renderValue={(selected) => selected.join(", ")}
>
<MenuItem value="all">
<Checkbox checked={isAllSelected} indeterminate={this.state.selectedItems.length > 0 && this.state.selectedItems.length < names.length} />
<ListItemText primary="Select All" />
</MenuItem>
{names.map((name: string) => (
<MenuItem key={name} value={name}>
<Checkbox checked={this.state.selectedItems.indexOf(name) > -1} />
<ListItemText primary={name} />
</MenuItem>
))}
</Select>
</FormControl>
);
};
}
export default withStreamlitConnection(MultiSelectComponent);
I have 2 issues:
-
It is quite strange that my component did not overflow
-
I cannot capture and return my select to streamlit
Please help me to fix it. Thank you so much