Reputation: 88
Please help me with this multiple menu handling events. I have dynamic menus and its corresponding menuitems in a json. I wanted to show menuitems declared under that particular parent menu, instead it is overlapping and showing all of the parents menuitems when a single menu button is clicked.
This is my Nvbar.js
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import { InputData } from '../InputJSON';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
navButton: {
margin: 'auto',
},
title: {
flexGrow: 1,
},
toolbar:{
backgroundColor: "orange",
},
}));
export default function ButtonAppBar() {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div className={classes.root}>
<Toolbar className={classes.toolbar}>
{Object.keys(InputData).map((item, index) => (
<div
className={classes.navButton}
key={index}
>
<Button
color="inherit"
onClick={handleClick}
>
{item} <i className='fas fa-caret-down' />
</Button>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
getContentAnchorEl={null}
anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
transformOrigin={{vertical: 'top', horizontal: 'center'}}
>
{InputData[item].map((menuitems, menuindex) =>
(
<MenuItem
key={menuindex}
selected={menuitems === item}
onClick={handleClose}
>
{menuitems.title}
</MenuItem>
)
)}
</Menu>
</div>
))
}
</Toolbar>
</div>
);
}
InputData.js
export const MenuItems =
{"furniture":
[
{
title: 'Marketing',
path: '/marketing',
cName: 'dropdown-link'
},
{
title: 'Consulting',
path: '/consulting',
cName: 'dropdown-link'
},
{
title: 'Design',
path: '/design',
cName: 'dropdown-link'
},
{
title: 'Development',
path: '/development',
cName: 'dropdown-link'
}
],
"mobiles":
[
{
title: 'iphone',
path: '/marketing',
cName: 'dropdown-link'
},
{
title: 'samsung',
path: '/consulting',
cName: 'dropdown-link'
},
{
title: 'oneplus',
path: '/design',
cName: 'dropdown-link'
},
{
title: 'sony',
path: '/development',
cName: 'dropdown-link'
}
],
"laptops":
[
{
title: 'iphone',
path: '/marketing',
cName: 'dropdown-link'
},
{
title: 'samsung',
path: '/consulting',
cName: 'dropdown-link'
},
{
title: 'oneplus',
path: '/design',
cName: 'dropdown-link'
},
{
title: 'sony',
path: '/development',
cName: 'dropdown-link'
}
],
"aircon":
[
{
title: 'iphone',
path: '/marketing',
cName: 'dropdown-link'
},
{
title: 'samsung',
path: '/consulting',
cName: 'dropdown-link'
},
{
title: 'oneplus',
path: '/design',
cName: 'dropdown-link'
},
{
title: 'sony',
path: '/development',
cName: 'dropdown-link'
}
],
"kitapp":
[
{
title: 'iphone',
path: '/marketing',
cName: 'dropdown-link'
},
{
title: 'samsung',
path: '/consulting',
cName: 'dropdown-link'
},
{
title: 'oneplus',
path: '/design',
cName: 'dropdown-link'
},
{
title: 'sony123',
path: '/development',
cName: 'dropdown-link'
}
],
};
Upvotes: 5
Views: 4412
Reputation: 326
Thanks @ericgio, Your solution worked like magic.
Hello every if someone dropped in here for table rows having similar dropdown in loop and repeating as per number of rows, please check my code below it would help saving your time.
Table rows containing same dropdown of content which had similar options, just made small changes as suggested and code is working as expected. my code changes are listed below.
UseState
const [actionDD, setActionDD] = useState(null)
for toggle dropdown
const actionDropdown = (index, e) => {
setActionDD({ [index]: e.currentTarget })
}
Button
<IconButton
onClick={e => {
actionDropdown(index, e)
}}
...other attributes
>
<MoreVertIcon />
</IconButton>
Inside Menu
<Menu
anchorEl={actionDD && actionDD[index]}
open={actionDD && Boolean(actionDD[index])}
...other attributes
>
<MenuItem >1</MenuItem>
<MenuItem >2</MenuItem>
<MenuItem >3</MenuItem>
</Menu>
Thank you all, Special thanks to @ericgio
Upvotes: 1
Reputation: 3519
You need to track each anchor element separately, according to which menu item has been clicked. You can do this by setting the element according to the item key:
export default function ButtonAppBar() {
const classes = useStyles();
const [anchorEl, setAnchorEl] = React.useState(null);
// Instead of tracking a single element, set the element according to
// the menu item's index.
const handleClick = (index, event) => {
setAnchorEl({ [index]: event.currentTarget });
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div className={classes.root}>
<Toolbar className={classes.toolbar}>
{Object.keys(InputData).map((item, index) => (
<div className={classes.navButton} key={index}>
<Button color="inherit" onClick={(e) => handleClick(index, e)}>
{item} <i className="fas fa-caret-down" />
</Button>
<Menu
anchorEl={
// Check to see if the anchor is set.
anchorEl && anchorEl[index]
}
keepMounted
open={
// Likewise, check here to see if the anchor is set.
Boolean(anchorEl && anchorEl[index])
}
onClose={handleClose}
getContentAnchorEl={null}
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
transformOrigin={{ vertical: "top", horizontal: "center" }}
>
{menuItems[item].map((menuitems, menuindex) => (
<MenuItem
key={menuindex}
selected={menuitems === item}
onClick={handleClose}
>
{menuitems.title}
</MenuItem>
))}
</Menu>
</div>
))}
</Toolbar>
</div>
);
}
Working sandbox: https://codesandbox.io/s/icy-haze-h0594
Upvotes: 6