Source:  Twitter logo

I would like to implement Google's Material UI Menu Item inside of a TableCell, as shown in their docs here, as seen below:

Here is my current approach:

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import {
  Grid,
  IconButton,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
  Paper,
  Menu,
  MenuItem,
  Button,
} from '@material-ui/core';
import { ExpandLess, ExpandMore } from '@material-ui/icons';

const styles = theme => ({});

const Questions = ({ data, classes, openMenu, anchorEls, handleClose }) => {
  const CustomTableCell = withStyles(theme => ({
    head: {
      backgroundColor: theme.palette.common.black,
      color: theme.palette.common.white,
    },
    body: {
      fontSize: 14,
    },
  }))(TableCell);

  const formatData = rawData => Object.keys(rawData).map(key => rawData[key]);

  const n = { key: 'hi', rating: 55, text: 'wassup' };

  return (
    <Grid container alignItems={'center'} direction={'column'} spacing={8}>
      <Paper className={classes.root}>
        <Button
          key="close"
          aria-label="Close"
          color="inherit"
          className={classes.close}
          onClick={e => openMenu('dude', e)}
        >
          <ExpandMore />
        </Button>
        <Menu
          id={`dude`}
          key="menu"
          anchorEl={anchorEls.dude}
          open={Boolean(anchorEls.dude)}
          onClose={e => handleClose('dude', e)}
        >
          <MenuItem onClick={e => handleClose('dude', e)}>Delete</MenuItem>
          <MenuItem onClick={e => handleClose('dude', e)}>Flag</MenuItem>
          <MenuItem onClick={e => handleClose('dude', e)}>
            Mark Answered
          </MenuItem>
        </Menu>
        <Table className={classes.table}>
          <TableHead>
            <TableRow>
              <CustomTableCell>Question</CustomTableCell>
              <CustomTableCell numeric>Rating</CustomTableCell>
              <CustomTableCell>Upvote</CustomTableCell>
              <CustomTableCell>Downvote</CustomTableCell>
              <CustomTableCell>Options</CustomTableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            <TableRow className={classes.row} key={n.key}>
              <CustomTableCell component="th" scope="row">
                {n.text}
              </CustomTableCell>
              <CustomTableCell numeric>{n.rating}</CustomTableCell>
              <CustomTableCell>
                <IconButton
                  key="close"
                  aria-label="Close"
                  color="inherit"
                  className={classes.close}
                  onClick={() => ''}
                >
                  <ExpandLess />
                </IconButton>
              </CustomTableCell>
              <CustomTableCell>
                <IconButton
                  key="close"
                  aria-label="Close"
                  color="inherit"
                  className={classes.close}
                  onClick={() => ''}
                >
                  <ExpandMore />
                </IconButton>
              </CustomTableCell>
              <CustomTableCell>
                <Button
                  key="close"
                  aria-label="Close"
                  color="inherit"
                  className={classes.close}
                  onClick={e => openMenu(n.key, e)}
                >
                  <ExpandMore />
                </Button>
                <Menu
                  id={`simple-menu-${n.key}`}
                  key="menu"
                  anchorEl={anchorEls[n.key]}
                  open={Boolean(anchorEls[n.key])}
                  onClose={e => handleClose(n.key, e)}
                >
                  <MenuItem onClick={e => handleClose(n.key, e)}>
                    Delete
                  </MenuItem>
                  <MenuItem onClick={e => handleClose(n.key, e)}>dude</MenuItem>
                  <MenuItem onClick={e => handleClose(n.key, e)}>choc</MenuItem>
                </Menu>
              </CustomTableCell>
            </TableRow>
          </TableBody>
        </Table>
      </Paper>
    </Grid>
  );
};

Questions.propTypes = {
  data: PropTypes.object.isRequired,
  anchorEls: PropTypes.object.isRequired,
  classes: PropTypes.object.isRequired,
  openMenu: PropTypes.func.isRequired,
  handleClose: PropTypes.func.isRequired,
};

Questions.defaultProps = {};

export default withStyles(styles)(Questions);

This is working, however the menu is not appearing in the correct place, even when passing in the related event e. I put in a dummy element before the table to test whether or not the table was affecting the menu, and found that the dummy worked just fine, as you can see in the screenshot below.

And the improperly placed menu from the button in the table:

Any ideas on what could be happening? Obviously, the context and anchorEl isn't correctly identifying the location on the page, but not sure what to do to combat that.

Problem in your openMenu function.You need to set the event target in your openMenu function, and set null in handleClose function. I am giving here a little example which may help you:

class DemoList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: [],
            anchorEls: []
        }
    }
    handleActionClick = (id, event) => {
        let { anchorEls } = this.state;
        anchorEls[id] = event.target;
        this.setState({ anchorEls });
    }
    handleActionClose = (id, event) => {
        let { anchorEls } = this.state;
        anchorEls[id] = null;
        this.setState({ anchorEls });
    }
    render() {
        let { classes } = this.props;
        const { data, anchorEls } = this.state;
        return (
            <Paper className="main">
                <Table className={classes.table} aria-label="simple table">
                    <TableHead>
                        <TableRow>
                            <TableCell>Dessert (100g serving)</TableCell>
                            <TableCell align="right">Calories</TableCell>
                            <TableCell align="right">Fat&nbsp;(g)</TableCell>
                            <TableCell align="right">Carbs&nbsp;(g)</TableCell>
                            <TableCell align="right">Action</TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {data.map(row => (
                            <TableRow key={row.id}>
                                <TableCell component="th" scope="row"> {row.name} </TableCell>
                                <TableCell align="right">{row.calories}</TableCell>
                                <TableCell align="right">{row.fat}</TableCell>
                                <TableCell align="right">{row.carbs}</TableCell>
                                <TableCell align="right">
                                    <IconButton
                                        aria-label="more"
                                        aria-controls="long-menu"
                                        aria-haspopup="true"
                                        onClick={e => this.handleActionClick(row.id, e)}
                                    >
                                        <MoreVert />
                                    </IconButton>
                                    <Menu
                                        id={row.id}
                                        anchorEl={anchorEls[row.id]}
                                        keepMounted
                                        open={Boolean(this.state.anchorEls[row.id])}
                                        onClose={e => this.handleActionClose(row.id, e)}
                                    >
                                        <MenuItem onClick={e => this.handleActionClose(row.id, e)}> View Details </MenuItem>
                                        <MenuItem onClick={e => this.handleActionClose(row.id, e)}> Assign </MenuItem>
                                    </Menu>
                                </TableCell>
                            </TableRow>
                        ))}
                    </TableBody>
                </Table>
            </Paper>
        )
    }
}
5 users liked answer #0dislike answer #05
Diptesh Atha profile pic
Diptesh Atha

After hacking away I found that removing the CustomTableCell declaration and changing all the CustomTableCells to normal TableCells resolved the problem. 😫 Not sure why that would fix it given that the CustomTableCell code was pulled straight from the Demos page.

1 users liked answer #1dislike answer #11
Dane Jordan profile pic
Dane Jordan

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).