Prevent event propagation on row click and dialog in material ui

Viewed 5528

I'm using and I have a table with a button inside. The button opens a Dialog and I need to be able to support clicking on the table row.
The problem is that with Portals (in react) - the events are propagated, so clicking inside the Dialog (that was opened after clicking on the button) - the click event on the table-row will get fired.

This is the row:

<TableRow onClick={rowClick}>
  <TableCell>Content 1</TableCell>
  <TableCell>Row clicked {count} times</TableCell>
  <TableCell>
    <MyDialog />
  </TableCell>
</TableRow>

This is the dialog:

<>
  <IconButton onClick={handleClickOpen}>
    <EditIcon />
  </IconButton>
  <Dialog disableBackdropClick open={open} onClose={handleClose}>
    <DialogTitle>Dialog</DialogTitle>
    <DialogContent>Some content</DialogContent>
    <DialogActions>
      <Button onClick={handleClose}>Cancel</Button>
      <Button onClick={handleClose}>Save</Button>
    </DialogActions>
  </Dialog>
</>

Here is a working example:
https://codesandbox.io/s/dazzling-hofstadter-gzwll

And this is an animated gif that shows the issue:
enter image description here

I know I can set the "rowClick" on each cell (and leave the last cell without it) but this is just an example and I'm looking for a more generic solution.

4 Answers

It took some time to find a proper solution, but the only way to prevent the propagation of the event was to add a "click" function on the dialog itself:

<>
  <IconButton onClick={handleClickOpen}>
    <EditIcon />
  </IconButton>
  <Dialog
    disableBackdropClick
    open={open}
    onClose={handleClose}
    onClick={handleDialogClick}
  >
    <DialogTitle>Dialog</DialogTitle>
    <DialogContent>Some content</DialogContent>
    <DialogActions>
      <Button onClick={handleClose} color="primary">
        Cancel
      </Button>
      <Button onClick={handleClose} color="primary">
        Save
      </Button>
    </DialogActions>
  </Dialog>
</>

And have the handleClickDialog function stop the event propagation:

const handleDialogClick = e => {
  e.stopPropagation();
}; 

Here is a working example:
https://codesandbox.io/s/cocky-violet-19uvd

it has nothing to do it e.stopPropagation();. The dialog and edit icon is wrapped with row and row has click function.

I would ask you to check this https://codesandbox.io/s/inspiring-bassi-b9hev

I made some changes. It will open and close the dialog box.

In your existing implementation icon is part of a dialog box which is wrong. you can check my code.

Hint:

 <TableBody>
            <TableRow onClick={rowClick}>
              <TableCell>Content 1</TableCell>
              <TableCell>Row clicked {count} times</TableCell>
              <TableCell>
                <IconButton onClick={() => setIsOpen(true)}>
                  <EditIcon /> // I change it here
                </IconButton>
              </TableCell>
            </TableRow>
          </TableBody>
...

      <MyDialog isOpen={isOpen} onClose={() => setIsOpen(false)} />

New DialogBox

 <Dialog
      disableBackdropClick
      open={props.isOpen}
      onClose={() => props.onClose()}
    >
      <DialogTitle>Dialog</DialogTitle>
      <DialogContent>Some content</DialogContent>
      <DialogActions>
        <Button onClick={() => props.onClose()}>Cancel</Button>
        <Button onClick={() => props.onClose()}>Save</Button>
      </DialogActions>
    </Dialog>

you need to disable row event click for action column using stopPropagation
which will fix the issue

  const handlerActionColmunClick = (event: React.MouseEvent<HTMLElement>) => {
    event.stopPropagation();
  };


    <TableBodyCell onClick={handlerActionColmunClick }>
                      <IconButton
                        aria-label="three-dot-action-menu"
                        aria-controls="customized-menu"
                            aria-haspopup="true"
                            onClick={handleActionMenuClick}
                          >
       ...........
    ...........
 ...........
Related