How to handle "outside" click on Dialog (Modal)?
Asked Answered
D

14

84

My box closes when clicking outside of the box making me lose all the input. I want my box to close only when clicking on the cancel button. I am not sure what is making it close when clicking outside. Any help?

I am using @material-ui/core

  _close() {
        DeviceCreationActions.close();
    }

render() {
        const actions = [
            <Button
                id="device-create-dialog-close"
                key="device-create-dialog-close"
                onClick={this._close}
            >
              {this.context.intl.formatMessage({id: 'Cancel'})}
            </Button>
        ];

        if (0 < this.state.stepIndex) {
            actions.push(<Button
                id="device-create-dialog-back"
                key="device-create-dialog-back"
                onClick={this._previousStep.bind(this)}
              >
                {this.context.intl.formatMessage({id: 'Back'})}
              </Button>
            );
        }

        if (
            (1 >= this.state.stepIndex && 0 < this.state['formStep' + this.state.stepIndex].length) ||
            (0 < this.state.stepIndex)
        ) {
            actions.push(<Button
                id="device-create-dialog-next"
                key="device-create-dialog-next"
                onClick={2 === this.state.stepIndex ? this._save.bind(this) : this._nextStep.bind(this)}
              >
                {this.context.intl.formatMessage({id: 2 === this.state.stepIndex ? 'Create' : 'Next'})}
              </Button>
            );
        }
Daubery answered 2/8, 2019 at 15:14 Comment(1)
Can you share the code in Box? or any more code involved?Tadd
T
68

I think what you need is disableBackdropClick passed down to <Modal /> component

<Modal disableBackdropClick />

You can also disable close Dialog on Esc key press with disableEscapeKeyDown prop

Tadd answered 2/8, 2019 at 17:40 Comment(2)
This is deprecated nowFlor
#65687553Daric
G
156

disableBackdropClick will not work in Material UI v5.

Dialog API (next)

You can use code from the migration guide to handle each closing source manually with the onClose prop by detecting the source of the closing event.

<Dialog onClose={handleClose} />

And use the handler to stop it

Javascript:

const handleClose = (event, reason) => {
    if (reason && reason === "backdropClick") 
        return;
    myCloseModal();
}

Typescript:

Add import to top of file:

import type { DialogProps } from "@mui/material";

Then add the handler:

const handleClose: DialogProps["onClose"] = (event, reason) => {
    if (reason && reason === "backdropClick")
        return;
    myCloseModal();
}
Giralda answered 28/5, 2021 at 20:30 Comment(4)
Nice this is the exact answer :)Maxon
or don't pass onCloseDecoct
@ Code Ninja this might work, but you lose benefits like close on ESC click which I encounteredMazuma
smartdevpreneur.com/how-to-disable-mui-dialog-backdrop-clickBeerbohm
T
68

I think what you need is disableBackdropClick passed down to <Modal /> component

<Modal disableBackdropClick />

You can also disable close Dialog on Esc key press with disableEscapeKeyDown prop

Tadd answered 2/8, 2019 at 17:40 Comment(2)
This is deprecated nowFlor
#65687553Daric
F
25

Just remove the onClose method

  <Dialog
     sx={{
       position: 'absolute',
       left: 300,
       top: 35
     }}
     maxWidth="lg"
    open={open}
    // onClose={handleClose}
   .....
Fructificative answered 18/10, 2021 at 23:19 Comment(2)
Removing onClose also removes the ability to close a dialog by pressing ESC keyBoucicault
With this you completely lose the onClose handlerPetrify
N
5
const handleClose = (event, reason) => {
    if (reason && reason == "backdropClick" && "escapeKeyDown") 
        return;
    myCloseModal();
}

This will prevent to modal to close on outside clicks and escape button

Niobe answered 12/7, 2022 at 11:43 Comment(0)
L
4

since disableBackdropClick is deprecated in the newest versions of material ui so the easier way to remove onClose from the dialog properties and add a button on DialogTitle and fire your handleClose function after a click on the button that will set the state of open dialog to false

<Dialog
  // onClose={handleClose} // the line to be removed
  open={dialog.open}
  fullWidth
  maxWidth="md"
  >
  <DialogTitle
    sx={{
      display: 'flex',
      alignItems: 'center',
    }}
  >
    <Typography
      variant="h5"
      textAlign="center"
      component="h1"
      gutterBottom
      sx={{
        pl: 2,
      }}
    >
      {dialog.action === 'add'
        ? 'Ajouter une question'
        : 'Editer la question'}
    </Typography>
    
    {/*Fire handleClose after a click on close button*/}
    <IconButton onClick={handleClose} sx={{ ml: 'auto' }}>
      <CloseIcon />
    </IconButton>
  </DialogTitle>
  <QuestionForm
    dimensionId={dimensionId}
    action={dialog.action}
    questionData={dialog.data}
    handleClose={handleClose}
    setQuestions={setQuestions}
    setRows={setRows}
  />
</Dialog>

enter image description here

Litchi answered 11/1, 2023 at 14:29 Comment(0)
S
2

In your Dialog tag remove the onClose event function. Then just add a button below let's say 'Cancel' then you can call function to close the dialog

const handleClose = () => {
 setOpen(false)
}

<Dialog
  fullWidth={true}
  open={open}
>
....
 <DialogActions>
    <Button onClick={handleClose} disabled={loading}>Cancel</Button>
 </DialogActions>
</Dialog>
Spermatozoid answered 22/9, 2022 at 11:59 Comment(0)
V
2
if backdrop/outside of dialog click then do nothing/don't close dialog. making sure the process is completed properly
const handleMeetingCreateDialogClose = (event, reason) => {
        if (reason && reason === "backdropClick")   return; 
        setFormData(formInitial);
        setMeetingCreateDialogOpen(false);
};
<Dialog open={meetingCreateDialogOpen} onClose={handleMeetingCreateDialogClose}  disableEscapeKeyDown  >
Valdis answered 30/8, 2023 at 14:57 Comment(0)
P
1

Simply add "disableBackdropClick" prop in your component. This will restrict(disable) outside click of your popup or dialog.

    //Example
    <DialogCss
      style={{ zIndex: 2000 }}
      open={ruleBoxOpen}
      keepMounted
      onClose={() => setRuleBoxOpen(false)}
      aria-labelledby="alert-dialog-slide-title"
      aria-describedby="alert-dialog-slide-description"
      disableBackdropClick
    >
Photoperiod answered 23/9, 2022 at 11:13 Comment(0)
C
0

You can create a similar component, like this one :

import React, { ReactNode } from "react";

export function CustomDialog(props: {
  open: boolean;
  children: ReactNode;
}) {
  if (!props.open) return <></>;
  return (
    <div
      style={{
        position: "fixed",
        top: "50%",
        left: "50%",
        transform: "translate(-50%, -50%)",
      }}
    >
      {props.children}
    </div>
  );
}

Hope this helps!

Cram answered 5/5, 2022 at 7:44 Comment(0)
N
0

This was my problem as well and no one seems to answer it quite well. This is what I did.

Remove the onClose from the <Dialog > wrapper, i.e. this is how the <Dialog> might look:

<Dialog
    sx={{
        position: 'absolute',
        left: 300,
        top: 35
    }}
    maxWidth="lg"
    open={open}
    // onClose={handleClose}      <<<<<<<
    ....
>

And finally, add the handleClose function to the onClick event of the close button.

<Button
    color="primary"
    size="large"
    type="submit"
    variant="contained"
    onClick={handleClose}
>
    Close
</Button>

Your problem will be solved.

Nook answered 11/6, 2022 at 5:18 Comment(0)
W
0

Here is my full solution to remove the flag because was descoped, but keeping the functionality.

This is the dialog:

  <Dialog
    open={showModal}
    disableBackdropClick
    disableEscapeKeyDown
    aria-labelledby="alert-dialog-title"
    aria-describedby="alert-dialog-description"
    onClose={handleDlgClose}
  >
    <DialogTitle id="alert-dialog-title">
      The title of the dialog
    </DialogTitle>
    <DialogContent>
      <DialogContentText id="alert-dialog-description">
        The message is here
        {bestScore} moves.
      </DialogContentText>
    </DialogContent>
    <DialogActions>
      <Button onClick={handleOk} color="primary">
        Restart
      </Button>
    </DialogActions>
  </Dialog>
enter code here

The function that intercepts the close event and if it comes from a click in the background and returns without closing the dialog:

const handleDlgClose = (event, reason) => {
  if (reason && reason == "backdropClick") {
    console.log('backdropClicked. Not closing dialog.')
    return;
  }

  setShowModal(false);
}

then handler and removing the property: ...

https://dev.to/teaganga/handle-dialogdisablebackdropclick-descoped-property-warning-in-mui-v5-2i35

Wandis answered 16/11, 2023 at 17:38 Comment(0)
M
0

From MUI version 5 the disableBackdropClick prop on the Modal component has been deprecated. Now we need to check for the reason in the onClose callback. As per the MUI 5 migration guide:

  <Dialog
    -  disableBackdropClick
    -  onClose={handleClose}
    +  onClose={(event, reason) => {
    +    if (reason !== 'backdropClick') {
    +      handleClose(event, reason);
    +    }
    +  }}
  />

MUI Migration Guide : Remove disablebackdropclick Prop

Mountford answered 2/4 at 6:27 Comment(0)
B
0

You may manage an outside click on the Dialog by utilizing the onClose prop and determining the reason for the closing event. This ensures that the Dialog will only shut when the cancel button is clicked, not when the user clicks outside the Dialog box. Here's how you can accomplish it:

const handleClose = (event, reason) => {
    if (reason && reason === "backdropClick") 
        return;
    DeviceCreationActions.close();
}

<Dialog onClose={handleClose}>
    {/* Dialog content */}
</Dialog>
Bathilda answered 2/4 at 9:13 Comment(0)
P
0

if you don't want to close the dialog on the backdrop click you can simply remove onClose prop from the dialog

<Dialog open={openDialog}>
        <DialogTitle>Titile</DialogTitle>
        <Divider />
        <DialogContent>
          <DialogContentText>
          ...
          <DialogContectText>
        </DialogContent>  
</Dialog>
Phlebotomy answered 7/5 at 12:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.