Reputation: 2720
I currently using a Select
component in my app.
I built a custom modal component that I want to launch instead of the list items when the select is clicked. Is there a way to override the handler for clicks on all portions of the component, such as icon, text field, and dropdown arrow to launch my modal? I want to take just the styling of this component essentially and override the onChange
and MenuItem
stuff.
<Select
value={props.selectedValue}
onChange={props.onTimeChange}
displayEmpty
startAdornment={
<InputAdornment position="start">
<DateRangeIcon />
</InputAdornment>
}
>
{/* DONT USE THESE MENU ITEMS AND USE CUSTOM MODAL INSTEAD */}
{/*<MenuItem value={-1} disabled>*/}
{/* Start Date*/}
{/*</MenuItem>*/}
{/*<MenuItem value={1}>Last Hour</MenuItem>*/}
{/*<MenuItem value={24}>Last Day</MenuItem>*/}
{/*<MenuItem value={24 * 7}>Last Week</MenuItem>*/}
{/*<MenuItem value={24 * 31}>Last Month</MenuItem>*/}
{/*<MenuItem value={''}>All</MenuItem>*/}
</Select>
Upvotes: 1
Views: 3085
Reputation: 80966
In order for it to make sense to leverage Select
while using an alternative display for the options, it is important that you provide it with menu items for all the allowed values, because the display of the selected item is based on finding a matching MenuItem
for the current value (though it would also be possible to provide the Select
with a single MenuItem
with a dynamic value and text matching whatever the current selected value is).
You can use a "controlled" approach for managing the open
state of the Select
using the open
and onOpen
props (you can leave out onClose
since the close should always be triggered by your custom display of the options). This way, rather than trying to override the different events that cause the Select
to open, you just let it tell you when it should open (via the onOpen
prop), but instead of opening the Select
, leave its open
prop as always false
and only open your custom popup.
Here's a working example:
import React from "react";
import InputAdornment from "@material-ui/core/InputAdornment";
import Button from "@material-ui/core/Button";
import DateRangeIcon from "@material-ui/icons/DateRange";
import Popover from "@material-ui/core/Popover";
import Box from "@material-ui/core/Box";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
export default function SimplePopover() {
const [value, setValue] = React.useState(1);
const [open, setOpen] = React.useState(false);
const selectRef = React.useRef();
const handleSelection = newValue => {
setValue(newValue);
setOpen(false);
};
return (
<Box m={2}>
<Select
ref={selectRef}
value={value}
onChange={e => setValue(e.target.value)}
displayEmpty
open={false}
onOpen={() => setOpen(true)}
startAdornment={
<InputAdornment position="start">
<DateRangeIcon />
</InputAdornment>
}
>
<MenuItem value={1}>Last Hour</MenuItem>
<MenuItem value={24}>Last Day</MenuItem>
<MenuItem value={24 * 7}>Last Week</MenuItem>
<MenuItem value={24 * 31}>Last Month</MenuItem>
<MenuItem value={""}>All</MenuItem>
</Select>
<Popover
id="simple-popover"
open={open}
anchorEl={selectRef.current}
onClose={() => handleSelection(value)}
anchorOrigin={{
vertical: "bottom",
horizontal: "left"
}}
transformOrigin={{
vertical: "top",
horizontal: "left"
}}
>
<Button onClick={() => handleSelection(1)}>Last Hour</Button>
<Button onClick={() => handleSelection(24)}>Last Day</Button>
</Popover>
</Box>
);
}
Here's a second example using a single, dynamic MenuItem for the selected value instead of a comprehensive set of menu items:
import React from "react";
import InputAdornment from "@material-ui/core/InputAdornment";
import Button from "@material-ui/core/Button";
import DateRangeIcon from "@material-ui/icons/DateRange";
import Popover from "@material-ui/core/Popover";
import Box from "@material-ui/core/Box";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
export default function SimplePopover() {
const [value, setValue] = React.useState(1);
const [text, setText] = React.useState("Last Hour");
const [open, setOpen] = React.useState(false);
const selectRef = React.useRef();
const handleSelection = (newValue, newText) => {
setValue(newValue);
setText(newText);
setOpen(false);
};
return (
<Box m={2}>
<Select
ref={selectRef}
value={value}
onChange={e => setValue(e.target.value)}
displayEmpty
open={false}
onOpen={() => setOpen(true)}
startAdornment={
<InputAdornment position="start">
<DateRangeIcon />
</InputAdornment>
}
>
<MenuItem value={value}>{text}</MenuItem>
</Select>
<Popover
id="simple-popover"
open={open}
anchorEl={selectRef.current}
onClose={() => handleSelection(value)}
anchorOrigin={{
vertical: "bottom",
horizontal: "left"
}}
transformOrigin={{
vertical: "top",
horizontal: "left"
}}
>
<Button onClick={() => handleSelection(1, "Last Hour")}>
Last Hour
</Button>
<Button onClick={() => handleSelection(24, "Last Day")}>
Last Day
</Button>
</Popover>
</Box>
);
}
Upvotes: 2