Colin Sygiel
Colin Sygiel

Reputation: 947

How do I show which item in the Menu List is selected with Material UI React?

I am trying to dynamically style the menu list items based on setting the selected prop to true or false.

I am trying to use the onClick method and to read the event.target.name, change the state of the value provided by each menu item and then finally use the selected prop to check if the value is true or false. For some reason, it is not picking up the event.taget.name that I am trying to log.

Above render:

constructor(props) {
  super(props);
  this.state = { 
    notFound: false,
    value: false,
    anchorEl: null,
    industry: ''
  };
}

handleIndustriesSelect = event => {
  this.setState({ [event.target.name]: event.target.value });
  console.log('target',event.target.name)
  this.handleIndustriesClose()
}

Below render

<Menu
  id="industries-menu"
  anchorEl={anchorEl}
  open={Boolean(anchorEl)}
  onClose={this.handleIndustriesClose}
  MenuListProps={{
    name: 'industry'
  }}
>
  <MenuItem value={'aerospace'} selected={this.state.industry === 'aerospace'} onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/aerospace'>Aerospace</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/automotive'>Automotive</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/energy'>Energy</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/industrial'>Industrial</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/marine'>Marine</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/medical-technologies'>Medical Technologies</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/tool-manufacturers'>Tool Manufacturers</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/mixed-parts'>Mixed Parts</MenuItem>
  <MenuItem onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/watch'>Watch</MenuItem>
</Menu>

Upvotes: 3

Views: 30248

Answers (2)

nine9stars
nine9stars

Reputation: 247

You can not use state to select the menu item because the states are not kept when you click the menu items every time. When you click the menu item, it is supposed to change the url and the component will be re-rendered.

So the solution is to check if the current location(url) is matched with the menu item's target url. If matched, the selected prop of menu item should be true. In order to get the current location as a prop in the component, you will need to use withRouter HOC of react-router.

Here is a full code that verify how this works. https://codesandbox.io/s/j432ox8255

import React from 'react';
import { Link} from 'react-router-dom';
import { withRouter } from 'react-router'
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';

class SimpleMenu extends React.Component {
  state = {
      notFound: false,
      value: false,
      anchorEl: null,
  };

  handleIndustriesOpen = event => {
    this.setState({ anchorEl: event.currentTarget });
  };

  handleIndustriesClose = () => {
    this.setState({ anchorEl: null });
  };

  render() {
    const { location: { pathname } } = this.props;
    const { anchorEl } = this.state;

    return (
      <div>
       <Button
          aria-owns={anchorEl ? 'industries-menu' : null}
          aria-haspopup="true"
          onClick={this.handleIndustriesOpen}
        >
          Open Menu
        </Button>
        <Menu
          id="industries-menu"
          anchorEl={anchorEl}
          open={Boolean(anchorEl)}
          onClose={this.handleIndustriesClose}
          MenuListProps={{
            name: 'industry'
          }}
        >
          <MenuItem selected={pathname === '/home/industry/aerospace'} onClick={this.handleIndustriesSelect} component={Link} to='/home/industry/aerospace'>Aerospace</MenuItem>
          <MenuItem selected={pathname === '/home/industry/automotive'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/automotive'>Automotive</MenuItem>
          <MenuItem selected={pathname === '/home/industry/energy'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/energy'>Energy</MenuItem>
          <MenuItem selected={pathname === '/home/industry/industrial'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/industrial'>Industrial</MenuItem>
          <MenuItem selected={pathname === '/home/industry/marine'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/marine'>Marine</MenuItem>
          <MenuItem selected={pathname === '/home/industry/medical-technologies'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/medical-technologies'>Medical Technologies</MenuItem>
          <MenuItem selected={pathname === '/home/industry/tool-manufacturers'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/tool-manufacturers'>Tool Manufacturers</MenuItem>
          <MenuItem selected={pathname === '/home/industry/mixed-parts'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/mixed-parts'>Mixed Parts</MenuItem>
          <MenuItem selected={pathname === '/home/industry/watch'} onClick={this.handleIndustriesClose} component={Link} to='/home/industry/watch'>Watch</MenuItem>
      </Menu>
      </div>
    );
  }
}

export default withRouter(SimpleMenu);

Upvotes: 7

amankkg
amankkg

Reputation: 5061

You need to set name explicitly on each MenuItem.

MenuListProps does apply to inner MenuList component only, not to MenuItems.

...

But, in your case I'd not use name prop, just set it in setState directly:

handleIndustriesSelect = event => {
  this.setState({ industry: event.target.value });

...

Also, it looks like e.target.value is also undefined, if so is true for you, then you have to pass value prop too, which is a sign of overcomplication.

Upvotes: 2

Related Questions