'How can Material-UI's Dialog allow interaction behind the dialog?
I am using Material-UI in my React app, and I have a Dialog that appears over several form elements after I click a button.
I also have that dialog set to allow it to be dragged using react-draggable.
When the dialog is showing, none of the form elements behind it are ale to be accessed. I realize it intuitively makes sense to block interaction with the elements behind the dialog.
However, I am trying to figure out how to have the dialog showing, and yet still being able to edit the form elements behind it.
Code example here:
Does anyone know if it's possible to show a MaterialUI Dialog and still be able to interact with form elements behind the dialog (ie, when the dialog is dragged away)?
Solution 1:[1]
It is possible, and without too much trouble! When the Dialog is opened, its root container is a div with a class of MuiDialog-root, spawned directly in your <body>. Instead of putting the react-draggable component around the dialog's PaperComponent, we put it around the entire dialog:
<Draggable
handle={'[class*="MuiDialog-root"]'}
cancel={'[class*="MuiDialogContent-root"]'}>
<Dialog
// Styling goes here
>
... // Dialog contents
</Dialog>
</Draggable>
Then, it's necessary to style the Dialog a little. We need to make sure to disable the backdrop, then bring the container size down so that when we click behind it, we are actually selecting other components:
<Dialog
open={open}
onClose={handleClose}
disableEnforceFocus // Allows other things to take focus
hideBackdrop // Hides the shaded backdrop
disableBackdropClick // Prevents backdrop clicks
PaperComponent={PaperComponent}
style={{
top: '30%', // Position however you like
left: '30%',
height: 'fit-content', // Ensures that the dialog is
width: 'fit-content', // exactly the same size as its contents
}}
>
...
</Dialog>
Note the PaperComponent property. As per the material-ui docs on draggable dialogs, this refers to the surface that holds the dialog contents. However, instead of wrapping the paper in a <Draggable>, we need to create this component for styling. If we don't, the PaperComponent will have large, obnoxious margins and won't fit properly in its parent.
function PaperComponent(props: PaperProps) {
// PaperProps is an import from '@material-ui/core'
return (
<Paper {...props} style={{ margin: 0, maxHeight: '100%' }} />
);
}
Be sure to place this function outside of the rendering component. Otherwise, every time the state changes, your dialog contents will be remounted. This was bad for me because I was using an Autocomplete field in the dialog, and every time I selected an option and did something with the onChange(), the text input would disappear. Changing the function scope fixed this problem.
Solution 2:[2]
disabling enforce focus can also disturb the origin and position Use disableAutoFocus
<Dialog
hideBackdrop={true}
disableBackdropClick
disableAutoFocus
...
>
....
</Dialog>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | April |
| Solution 2 | Priyanshu Dwivedi |
