Is there a way to trigger Material-UI SpeedDialAction onClick events only when the SpeedDial is open and clicked, not when it is hovered over?

After making a modification to material-ui's <SpeedDial> component by removing the onMouseEnter={handleOpen} prop, I noticed that the onClick event within the <SpeedDialAction> component no longer triggers when clicking on a menu item. It seems like there might be a key concept that I am overlooking.

  return (
    <SpeedDial
      ariaLabel="Add"
      className={classes.root}
      icon={<SpeedDialIcon />}
      onClick={handleClick}
      onClose={handleClose}
      onBlur={handleClose}
      // onMouseEnter={handleOpen}
      // onMouseLeave={handleClose}
      open={open}
      direction={mobile ? 'up' : 'down'}
    >
      {actions.map(action => (
        <SpeedDialAction
          key={action.name}
          icon={action.icon}
          tooltipTitle={action.name}
          tooltipOpen
          classes={{ staticTooltipLabel: classes.staticTooltipLabel }}
          onClick={e => {
            e.preventDefault();
            alert('x');
          }}
        />
      ))}
    </SpeedDial>
  );

Answer №1

When using the preventDefault function, it does not stop the click event from bubbling up to the parent element (which seems to be your goal).

To achieve this, you should utilize the stopPropagation method instead:

<SpeedDial
  ariaLabel="Add"
  className={classes.SpeedDial}
  icon={<SpeedDialIcon />}
  onClick={handleClick}
  open={open}
>
  {actions.map(action => (
    <SpeedDialAction
      key={action.name}
      icon={action.icon}
      tooltipTitle={action.name}
      tooltipOpen
      onClick={e => {
        e.stopPropagation();
        alert("x");
      }}
    />
  ))}
</SpeedDial>

For a demonstration, you can view the example here: https://codesandbox.io/s/speeddial-open-on-click-rleg5?file=/demo.js

Answer №2

I opt to assign the onclick handler to the icon instead

  • (more precisely, the parent <button> (the blue circle) of the icon
    otherwise, you have to click at the exact position of icon, instead of the blue circle

  • -- but this feels hacky...
    -- wish MaterialUi provides better Api for SpeedDial for this...)

code:

  • @watch for this part:

            <SpeedDialIcon
              ref={React.useCallback((elt: HTMLElement | null | any) => {
                if (elt instanceof HTMLElement) {
                  if (elt.parentElement instanceof HTMLButtonElement) {
                    elt.parentElement.onclick = () => set_show((show) => !show);
    
  • full code:

    const PanelVisbilityController: React.FC<{
      set_show_MediaStreamLocalSelfGridPanel_rst: React.Dispatch<React.SetStateAction<boolean>>;
      set_show_LobbyUserListPanel_rst: React.Dispatch<React.SetStateAction<boolean>>;
      set_show_VideoConnectionControlPanel_rst: React.Dispatch<React.SetStateAction<boolean>>;
      set_show_TextChat_rst: React.Dispatch<React.SetStateAction<boolean>>;
      set_show_DebugPanel_rst: React.Dispatch<React.SetStateAction<boolean>>;
    }> = React.memo(({ set_show_MediaStreamLocalSelfGridPanel_rst, set_show_LobbyUserListPanel_rst, set_show_VideoConnectionControlPanel_rst, set_show_TextChat_rst, set_show_DebugPanel_rst }) => {
      const [show, set_show] = React.useState<boolean>(true);
      // reversed order ...
      const actions = [
        { icon: <VideoLibraryIcon />,       name: 'MediaStream',        onClick: () => set_show_MediaStreamLocalSelfGridPanel_rst(show => !show) },
        { icon: <VideoChatIcon />,          name: 'ConnectionAnchor',   onClick: () => { console.log('// Do nothing')} },
        { icon: <VideoCameraFrontIcon />,   name: 'LobbyUserList',      onClick: () => set_show_LobbyUserListPanel_rst(show => !show) },
        { icon: <VideogameAssetOutlined  />,name: 'ControlPanel',       onClick: () => set_show_VideoConnectionControlPanel_rst(show => !show) },
        { icon: <ChatIcon />,               name: 'TextChat',           onClick: () => set_show_TextChat_rst(show => !show) },
        { icon: <BugReportIcon />,          name: 'DebugPanel',         onClick: () => set_show_DebugPanel_rst(show => !show) },
      ]; // prettier-ignore
      return (
        <SpeedDial
          ariaLabel="SpeedDial PanelVisbilityController"
          sx={{ position: 'fixed', bottom: 16, right: 16 }}
          icon={
            <SpeedDialIcon
              ref={React.useCallback((elt: HTMLElement | null | any) => {
                if (elt instanceof HTMLElement) {
                  if (elt.parentElement instanceof HTMLButtonElement) {
                    elt.parentElement.onclick = () => set_show((show) => !show);
                  } else {
                    console.warn('internal structure of material-ui SpeedDialIcon is changed, hack doesnt work, fall back to default handling');
                    elt.onclick = () => set_show((show) => !show);
                  }
                } else if (elt === null) {
                  // @do_nothing react thing ... elt is null
                } else {
                  // console.log(typeof elt);
                  // console.log(elt.constructor.name);
                  console.error('I may use the ref wrong in react,, to access to the dom element...');
                }
              }, [])}
              // onClick={() => set_show((show) => !show)}
            />
          }
          open={show}
        >
          {actions.reverse().map((action) => (
            <SpeedDialAction
              key={action.name}
              icon={action.icon}
              tooltipTitle={action.name}
              onClick={(ev) => {
                // ;not_good, clicking the icon inside also triggers; () => set_show((show) => !show);
                // ;not_good, clicking the blank region also triggers; []
                // ;not_good, clicking the blank region also triggers; You should use the stopPropagation instead:
                // ;not_good, clicking the blank region also triggers; <>
                // ;not_good, clicking the blank region also triggers; https://stackoverflow.com/questions/61649335/how-do-i-get-material-ui-speeddialaction-onclick-events-to-fire-when-speeddial-i
                // ;not_good, clicking the blank region also triggers; ev.stopPropagation();
                action.onClick();
              }}
              // open={false}
            />
          ))}
        </SpeedDial>
      );
    });
    

In a different respond post.
The implementation of e.stopPropagation(); seems to somewhat address the issue,
however, it still leads to the concern of

clicking the blank region also triggers
-- not limited solely to the blue circle button.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

AJAX - Alert with a beep sound each time a new entry is inserted into the database table

Having trouble determining the condition to test for when a new record is added to the database table. Can anyone lend a hand? Here's a snippet of the data retrieved from the database: ['Paul Abioro', '<a href="/cdn-cgi/l/email-prot ...

AngularJS $scope changes not reflecting in the view

Struggling with a persistent issue in my angularJS $scope. I've been working on updating an array within a controller function, and even though the values are changing based on console logs, the view isn't reflecting those changes. Here's wh ...

Generating interactive elements in VUE is key

I am unsure about how to dynamically create components without using the <component :is=''> tag. I would like to insert a component into the DOM through JavaScript. Similar to how you would add a new modal in jQuery with $("body").append(" ...

Encountering a syntax error while attempting to import modules from amCharts

Recently, I have been attempting to incorporate amcharts into my project using npm. After running the command npm install@amcharts/amcharts4, I noticed that all the necessary modules were now present in my node_modules folder and package.json file. Specifi ...

Notification not appearing in PHP

When working with a specific php file, I am encountering an issue where the alert box I have placed before the header is being ignored and the header is executed directly. Can anyone assist me in resolving this issue? Any help would be greatly appreciate ...

Older versions of Android, specifically Android 7 or lower, seem to encounter issues with Apis in React Native when utilizing axios. Fortunately, this problem doesn

For fetching the data, I utilized the 'axios' library. Surprisingly, it works flawlessly on newer Android devices (specifically Android 9 and 10). However, when it comes to older devices like Android 7 or earlier, a persistent Network Error occur ...

The digest string for the crypto.pbkdf2Sync function is malfunctioning

I've been working on revamping the authentication system for an old application that previously ran on node 4.5, but I keep encountering an error whenever I attempt to log in. TypeError [ERR_INVALID_ARG_TYPE]: The "digest" argument must be one of type ...

The UseEffect function ceases to function properly upon refreshing the website

I'm currently using ReactJS for a project. I have a form that is intended to serve as the configuration for another form. The structure of this specific form is as follows: const [startingDate, setStartingDate] = useState(); const [endingDate, set ...

Suggestions on enabling read-only mode for MUI Autocomplete?

I've been struggling to make the @mui/material/Autocomplete component read only. Even when I try returning a <TextField readOnly /> component in the renderInput function, the drop-down menu still triggers onChange events. I attempted using < ...

Try utilizing multiple URLs to trigger separate AJAX requests with a single click

I am looking to utilize multiple JSON files from different URL APIs simultaneously. Each URL will serve a different purpose - populating table headers with one URL, and table information with two or three URLs. Currently, my code looks like this: $(docum ...

Leveraging personalized design elements from a theme in Material UI without the need for makeStyles

Is there a way to access the theme.customElements.actionButton in MyComponent without relying on makeStyles? For instance, can I directly use className={theme.customElements.actionButton}? theme.js const theme = createMuiTheme({ customElements: { ...

Retrieving JSON information from a PHP script with AJAX

I am currently experiencing an issue with my PHP script, 'getNews.php'. Despite working correctly in the terminal and returning the expected data, I am encountering difficulties when trying to retrieve this information through JavaScript. <?p ...

Clearing a value with active getOptionSelected in Material-UI Autocomplete

I am using a Material-UI Autocomplete component and here is the code snippet: <Autocomplete onFocus={() => setFocusedProject(true)} onBlur={() => setFocusedProject(false)} ...

Scrollbar in an HTML selection tag

Is there a way to add a scroll bar to an HTML select box without using JavaScript? Alternatively, is there a JavaScript library that can achieve this behavior? Also, I'm looking for a redesign of the interface where I have two select boxes and items ...

Firebase authentication encountered an error due to a network request failure

Utilizing firebase Hosting to host my website, I am encountering a persistent error when attempting to login using email/password. This is the JavaScript code that I am using: window.onload = () => initApp(); //Initialize screen function initApp(){ ...

guide on adding a variable to the link_to path

In my attempt to incorporate a variable into the link_to function below: <%= link_to '<button type = "button">Players</button>' .html_safe, live_players_path(:Team => @tmf) %> Whenever I click on this link, it seems to ...

Jest tutorial: mocking constructor in a sub third-party attribute

Our express application uses a third-party module called winston for logging purposes. const express = require('express'); const app = express(); const { createLogger, transports } = require('winston'); const port = process.env.PORT | ...

ESLint error caught off guard by function expression in customized MUI Snackbar Component with Alert

Struggling to create a personalized MUI Snackbar using the MUI Alert example from the official Documentation, but facing ESlint errors: error Unexpected function expression prefer-arrow-callback error Prop spreading is forbidden react/jsx-props-no-s ...

Issue with parent-child communication in React.js causing malfunction

I am facing an issue with maintaining state between two different JavaScript files using React. The parent class, break.js, is defined as follows: export default function AlertDialog(props) { const [demoOpen, setDemoOpen] = React.useState(true); ...

Collaborating and monitoring data between controllers

A unique challenge has arisen as we implement a tree-style navigation element that must communicate with other directives/controllers. The main objectives are: Keep track of the current selection, Detect when the row selection changes. The task at hand ...