Reputation: 51
I tried to use multiple popover within a component. For ex, in below code I have two popovers, but when clicking any of the two button, both the popovers are opened. How can we handle the onclick to open corresponding popover?
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
<Tabs variant="fullWidth" value={value} onChange={onNavChange} indicatorColor="transparent">
<Tab label="Menu 1" className={classes.navTab} component={Link} to="./Menu1"></Tab>
<Tab label="Menu 2" onClick={handleClick} aria-describedby="menu2Popover" aria-haspopup="true"></Tab>
<Tab label="Menu 3" component={Link} to="./Menu3"></Tab>
<Tab label="Menu 4"onClick={handleClick} aria-describedby="menu4Popover" aria-haspopup="true"></Tab>
</Tabs>
<Popover
id="menu2Popover" open={Boolean(anchorEl)} onClose={handleClose}
anchorEl = {anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}>
<MenuList>
<MenuItem>Submenu 1</MenuItem>
<MenuItem>Submenu 2</MenuItem>
</MenuList>
</Popover>
<Popover
id="menu4Popover" open={Boolean(anchorEl)} onClose={handleClose}
anchorEl = {anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'left',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}>
<MenuList>
<MenuItem>Submenu 3</MenuItem>
<MenuItem>Submenu 4</MenuItem>
</MenuList>
</Popover>
Upvotes: 5
Views: 12151
Reputation: 1
You just need to give separate placeholder for popoverContent like "name + index"
, which is unique and sends the index as id in the handler function
and set it in state
then in open check is
index == your state where id is stored.
it will solve your problem.
const [id,setId] = useState(null)
const handleDropDown = (index) => {
setId(index)
}
<Popover placement="bottom" open={index == id} handler={() => handleDropDown(index)}>
<PopoverContent placeholder={`name-${index}`}>
Upvotes: 0
Reputation: 1220
You need to use different anchorEl
's for each Popover:
import * as React from "react";
import { render } from "react-dom";
import { MenuList, MenuItem, Popover, Tabs, Tab } from "@material-ui/core";
import "./styles.css";
interface CustomMenuItem {
anchorEl: null | HTMLElement;
child: any;
}
function Popover1() {
return (
<MenuList>
<MenuItem>Submenu 1</MenuItem>
<MenuItem>Submenu 2</MenuItem>
</MenuList>
);
}
function Popover2() {
return (
<MenuList>
<MenuItem>Submenu 3</MenuItem>
<MenuItem>Submenu 4</MenuItem>
</MenuList>
);
}
function App() {
const [popover1, setPopover1] = React.useState<CustomMenuItem>({
anchorEl: null,
child: <Popover1 />
});
const [popover2, setPopover2] = React.useState<CustomMenuItem>({
anchorEl: null,
child: <Popover2 />
});
return (
<div className="App">
<Tabs variant="fullWidth" indicatorColor="transparent">
<Tab label="Menu 1" />
<Tab
value="Tab2"
label="Menu 2"
onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
setPopover1({ ...popover1, anchorEl: event.currentTarget })
}
aria-describedby="menu2Popover"
aria-haspopup="true"
/>
<Tab label="Menu 3" />
<Tab
label="Menu 4"
onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
setPopover2({ ...popover2, anchorEl: event.currentTarget })
}
aria-describedby="menu4Popover"
aria-haspopup="true"
/>
</Tabs>
<Popover
id="menu2Popover"
open={Boolean(popover1.anchorEl)}
onClose={() => setPopover1({ ...popover1, anchorEl: null })}
anchorEl={popover1.anchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "left"
}}
transformOrigin={{
vertical: "bottom",
horizontal: "left"
}}
>
{popover1.child}
</Popover>
<Popover
id="menu4Popover"
open={Boolean(popover2.anchorEl)}
onClose={() => setPopover2({ ...popover2, anchorEl: null })}
anchorEl={popover2.anchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "left"
}}
transformOrigin={{
vertical: "bottom",
horizontal: "left"
}}
>
{popover2.child}
</Popover>
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Look at the codesandbox. If you have any further questions let me know and I can update my answer.
Upvotes: 4
Reputation: 1985
another sample with one Popover
import React from "react";
import { withStyles } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Tabs from "@material-ui/core/Tabs";
import Tab from "@material-ui/core/Tab";
import Popover from "@material-ui/core/Popover";
import MenuList from "@material-ui/core/MenuList";
import MenuItem from "@material-ui/core/MenuItem";
const styles = theme => ({
root: {
flexGrow: 1,
backgroundColor: theme.palette.background.paper,
textTransform: "none"
}
});
class SimpleTabs extends React.Component {
state = {
value: 0,
anchorEl: null,
popno: -1
};
handlePopoverClose = () => {
this.setState({ anchorEl: null, popno: -1 });
};
handleClick = (e, _popno) => {
this.setState({ anchorEl: e.currentTarget, popno: _popno });
};
handleChange = (event, value) => {
this.setState({ value });
};
render() {
const { classes } = this.props;
const { value } = this.state;
return (
<div className={classes.root}>
<AppBar position="static">
<Tabs value={value} onChange={this.handleChange}>
<Tab label="Tab 1" onClick={e => this.handleClick(e, 1)} />
<Tab label="Tab 2" onClick={e => this.handleClick(e, 2)} />
<Tab label="Tab 3" onClick={e => this.handleClick(e, 3)} />
</Tabs>
<Popover
id="menu2Popover"
open={this.state.anchorEl !== null}
onClose={this.handlePopoverClose}
anchorEl={this.state.anchorEl}
>
{this.state.popno === 1 && (
<MenuList>
<MenuItem>Tab 1 - Submenu 1</MenuItem>
<MenuItem>Tab 1 - Submenu 2</MenuItem>
</MenuList>
)}
{this.state.popno === 2 && (
<MenuList>
<MenuItem>Tab 2 - Submenu 1</MenuItem>
<MenuItem>Tab 2 - Submenu 2</MenuItem>
</MenuList>
)}
{this.state.popno === 3 && (
<MenuList>
<MenuItem>Tab 3 - Submenu 1</MenuItem>
<MenuItem>Tab 3 - Submenu 2</MenuItem>
</MenuList>
)}
</Popover>
</AppBar>
</div>
);
}
}
export default withStyles(styles)(SimpleTabs);
answer output https://codesandbox.io/s/material-tabs-demo-tpugw
Upvotes: 1