5

I have three actions supporting my SpeedDialAction, however when I try to log the event of the individual actions onClick, I get undefined.

I have tried using different functions as actions, also tried arrow function syntax in the method call

onClick={e => action.action(e)}

and

onClick={action.action}

The actions:

const actions = [
    { icon: <Add />, name: 'Product', action: handleDialogOpen },
    { icon: <Add />, name: 'Addon', action: handleDialogOpen },
    { icon: <Label />, name: 'Tag', action: handleDialogOpen }
  ]

The SpeedDial:

<SpeedDial
          ariaLabel='SpeedDial example'
          className={classes.speedDial}
          icon={<SpeedDialIcon />}
          onBlur={handleClose}
          onClick={handleClick}
          onClose={handleClose}
          onFocus={handleOpen}
          onMouseEnter={handleOpen}
          onMouseLeave={handleClose}
          open={open}
        >
          {actions.map(action => (
            <SpeedDialAction
              tooltipOpen
              key={action.name}
              icon={action.icon}
              tooltipTitle={action.name}
              onClick={action.action}
            />
          ))}
        </SpeedDial>

handleDialogOpen simply tries to log the event

I expect the output being an event object, not undefined.

Edric
  • 24,639
  • 13
  • 81
  • 91
Addibro
  • 107
  • 1
  • 8

3 Answers3

8

You can define an extra object item in actions array.

const actions = [
    { icon: <Add />, name: 'Product', action: handleDialogOpen, operation: 'product'},
    { icon: <Label />, name: 'Tag', action: handleDialogOpen , operation: 'tag' }
  ]

Now you need to call a handler function and pass the operation value as a parameter:

//handler function
 function handleClick (e,operation){
   e.preventDefault();
   if(operation=="product"){
     // do something 
   }else if(operation=="tag"){
     //do something else
   }
   setOpen(!open);// to close the speed dial, remove this line if not needed.
 };
<SpeedDial
          ariaLabel='SpeedDial example'
          className={classes.speedDial}
          icon={<SpeedDialIcon />}
          onBlur={handleClose}
          onClick={handleClick}
          onClose={handleClose}
          onFocus={handleOpen}
          onMouseEnter={handleOpen}
          onMouseLeave={handleClose}
          open={open}
        >
          {actions.map(action => (
            <SpeedDialAction
              tooltipOpen
              key={action.name}
              icon={action.icon}
              tooltipTitle={action.name}
              onClick={(e) => {
                      handleClick(e.action.operation)
                 }}
            />
          ))}
        </SpeedDial>
diazlp
  • 552
  • 5
  • 9
Neo
  • 366
  • 5
  • 15
  • Multiple `onClick` handlers are confusing here - specifically it's the `SpeedDialAction` and should be `action.operation` passed in the handler, not `actions.operation`. – Jason Sturges Aug 18 '21 at 20:41
0

Here is a working code on Typescript based on Material UI 5.13.14 https://mui.com/material-ui/react-speed-dial/

Optional: Define menuOptions

enum menuOptions {
  'MENU',
  'COMPARE',
  'SHARE',
}

Define your actions. Make shure to add the operation field.

const actions = [
  { icon: <List />, name: 'Menú', operation: menuOptions.MENU },
  { icon: <Compare />, name: 'Comparar', operation: menuOptions.COMPARE },
  { icon: <Share />, name: 'Compartir', operation: menuOptions.SHARE },
]

Now create the SpeedDial component. Make sure to add onClick={(e) => { handleClick(e, action.operation) }} in SpeedDialAction

  return (
    <>
      <SpeedDial
        ariaLabel="Menu"
        sx={{
          position: 'fixed',
          bottom: 20,
          right: 20,
        }}
        onClick={handleOpen}
        open={open}
        icon={<SpeedDialIcon />}
        direction="up"
      >
        {actions.map((action) => (
          <SpeedDialAction
            key={action.name}
            icon={action.icon}
            tooltipTitle={action.name}
            onClick={(e) => {
              handleClick(e, action.operation)
            }}
          />
        ))}
      </SpeedDial>
    </>
  )
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 06 '23 at 17:45
0

Also you may do this. Set your handler that closes your modal. And in the onClick, set an anonymous activating the action function and closing the modal. :

const handleClose = () => setOpen(false);


<SpeedDial
      ariaLabel='SpeedDial example'
      className={classes.speedDial}
      icon={<SpeedDialIcon />}
      onBlur={handleClose}
      onClick={handleClick}
      onClose={handleClose}
      onFocus={handleOpen}
      onMouseEnter={handleOpen}
      onMouseLeave={handleClose}
      open={open}
    >
      {actions.map(action => (
        <SpeedDialAction
          tooltipOpen
          key={action.name}
          icon={action.icon}
          tooltipTitle={action.name}
          onClick={() => {
            action.action()
            handleClose()  }}
        />
      ))}
    </SpeedDial>