17

I'm using Material UI for Menu and Menu Item. I'm trying to get the value of a menu item, but it doesn't work.

This is my code :

<Menu value= { this.state.selectedItem }>
  <MenuItem onClick={this.listClicked} 
    leftIcon={
      <FontIcon 
        className="material-icons"
        style={{ color: 'white', margin: '0' }}>
          format_list_bulleted
      </FontIcon>
    }
  />     
  <MenuItem onClick={this.settingClicked} 
    leftIcon={
      <FontIcon 
        className="material-icons"
        style={{ color: 'white', margin: '0' }}>
          settings
      </FontIcon>
    } 
  />
</Menu>

public listClicked = (value) => {
  this.setState({
    selectedItem :value
  })
  console.log(this.state.selectedItem)
}

I don't get the value, and in the console of navigator I have an object.

Can you help me?

Thank you

c-chavez
  • 7,237
  • 5
  • 35
  • 49
Anaïs Saez
  • 1,259
  • 5
  • 20
  • 38

10 Answers10

29

Use a data-attribute on the menu item and access it from the currentTarget of the click event. Note that data-my-value attribute becomes myValue on event.currentTarget.dataset.

const handleClick = event => {
    const { myValue } = event.currentTarget.dataset;
    console.log(myValue) // --> 123
}

<MenuItem
    data-my-value={123}
    onClick={handleClick}
>
    <div>text</div>
</MenuItem>

Why currentTarget instead of target? The currentTarget refers to the element that the event listener is directly attached to while the target refers to the specific element within MenuItem, such as some div, that is clicked on. That div does not have the data-my-value attribute and as such the target wouldn't have myValue on its dataset. So use currentTarget in this case.

Related: How to access custom attributes from event object in React?

Christiaan Westerbeek
  • 10,619
  • 13
  • 64
  • 89
7

In the Material UI Menu component, firing functions when selecting a menu item is best done with the onChange handler of the parent Menu component instead of onClick handlers for each separate item. The signature of the onChange callback is function(event: object, value: any) => void, so you can give each of your MenuItems a separate value prop, and this will be available as the second argument in your onChange handler. Like this:

<Menu value= { this.state.selectedItem } onChange={ this.menuClicked }>
  <MenuItem value="list" leftIcon={
    <FontIcon className="material-icons">format_list_bulleted</FontIcon>
  } />     
  <MenuItem value="settings" leftIcon={
    <FontIcon className="material-icons">settings</FontIcon>
  } />
</Menu>

...

public menuClicked = (event, value) => {
  this.setState({
    selectedItem: value
  })
  console.log(this.state.selectedItem)
}
Waiski
  • 9,214
  • 3
  • 21
  • 30
7

I used NativeEvent and it works for me.

handleClose = (ev) => {
        this.setState({
            anchorEl: null
        });
        console.log(ev.nativeEvent.target.outerText);
    };

Try like this please.

Elman Huseynov
  • 1,127
  • 1
  • 8
  • 18
6

Menu does not have onChange defined in the API and it did not work for me because it is never called. What works for me was an ugly solution:

<MenuItem onClick={this.handleClose.bind(this, 'valueHere')}>Text here</MenuItem>

Hernan
  • 69
  • 1
  • 3
6

Try e.target.innerText in MenuItem onClick.

const Menu = () => {
    const [anchorEl, setAnchorEl] = useState(null)

    const handleClick = event => {
        setAnchorEl(event.currentTarget)
    }

    const handleClose = e => {
        console.log(e.target.innerText) // => This logs menu item text.
        setAnchorEl(null)
    }

    return (
        <div>
            <Button onClick={handleClick}>Open Menu</Button>
            <Menu anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleClose}>
                <MenuItem onClick={handleClose}>Profile</MenuItem>
                <MenuItem onClick={handleClose}>My account</MenuItem>
                <MenuItem onClick={handleClose}>Logout</MenuItem>
            </Menu>
        </div>
    )
}
Gaurav
  • 857
  • 3
  • 21
  • 29
3

Use a feature in JavaScript called curry

This is in menu

 <MenuItem  onClick={this.closeDrawer("ProductPage")}>
        Products
 </MenuItem>

This is in handler

closeDrawer = key => event => {
    console.log("=> closeDrawer key", key);
    this.setState({ open: false });
  };

Then you would see something like below in JavaScript console

=> closeDrawer key ProductPage
iwan
  • 7,269
  • 18
  • 48
  • 66
1

You can also get the value like this

<MenuItem key={menu.id} primaryText={menuItem.name} onClick = {this.onClickButton} menuItems = {this.subMenu(menuItem.children)}/> 

and then onClickButton like this

onClickButton = (ev) => {
      if(ev.target.innerText === 'light') { // light is the value of menuitem in string
        this.props.dispatch(changeTheme('light'))
      } 
    }
tariq zafar
  • 659
  • 7
  • 24
0

The parameter that is passed to the onClick handler is an event not a value. You have to extract the value from the event.

public listClicked = (event) => {
        this.setState({
            selectedItem :event.target.value
        },()=>{
       console.log(this.state.selectedItem)
        })
    }

Also move the console.log as a callback as that way it is called only after the state change has taken place.

mrinalmech
  • 2,065
  • 1
  • 20
  • 18
  • The value is not an attribute of event.target. event.target has a
  • element which contains the value. Getting it is not so easy.
  • – Roger Veciana Jun 20 '18 at 08:28