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)?
The dialog was meant to block all other interaction so the user can focus on its contents. Anyway, I found one solution, probably not the better but is working here, the code is this:
<Dialog
hideBackdrop // Disable the backdrop color/image
disableEnforceFocus // Let the user focus on elements outside the dialog
style={{ position: 'initial' }} // This was the key point, reset the position of the dialog, so the user can interact with other elements
disableBackdropClick // Remove the backdrop click (just to be sure)
...
>
...
</Dialog>
Here a working example
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With