如何处理对话框(模态框)之外的点击?

75

点击盒子外部时,我的框会关闭,导致我失去所有输入内容。我希望只有在点击取消按钮时才关闭。我不确定是什么导致了在点击外部时关闭。请帮忙解决一下吗?

我正在使用@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>
            );
        }

你能在Box里分享代码吗?还有其他的代码涉及吗? - Adolfo Onrubia
11个回答

135

disableBackdropClick在Material UI v5中将不起作用。

Dialog API (next)

您可以使用迁移指南中的代码,通过检测关闭事件的来源并使用onClose prop手动处理每个关闭源。

<Dialog onClose={handleClose} />

使用处理程序停止它

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

3
好的,这是精确的答案 :) - koshur
3
or don't pass onClose - Code Ninja
@ Code Ninja 这可能有效,但你会失去一些好处,比如在我遇到的情况下,可以通过按 ESC 键关闭。 - Michael
https://smartdevpreneur.com/how-to-disable-mui-dialog-backdrop-click/ - Akhilesh Sinha

68

我认为你需要将 disableBackdropClick 传递给 <Modal /> 组件

<Modal disableBackdropClick />

您还可以通过disableEscapeKeyDown属性禁用按下Esc键时关闭对话框


24
现在这个已经被弃用了。 - The Coder
https://dev59.com/GL_pa4cB1Zd3GeqP-QHS - Wickramaranga

19

只需移除 onClose 方法即可。

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

6
移除 onClose 也会移除通过按下 ESC 键关闭对话框的功能。 - moshyfawn
2
使用此方法,您将完全失去 onClose 处理程序。 - Mayer Spitz

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

这将防止模态框在外部点击和按下 escape 键时关闭


3

由于最新版的 Material UI 已经弃用了 disableBackdropClick,因此更简单的方法是从对话框属性中删除 onClose,并在 DialogTitle 上添加一个按钮,在单击按钮后触发你的 handleClose 函数,该函数将关闭对话框的状态设置为 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


2
在您的对话框标签中删除onClose事件函数。然后只需在下面添加一个按钮,比如说“取消”,然后就可以调用函数关闭对话框。
const handleClose = () => {
 setOpen(false)
}

<Dialog
  fullWidth={true}
  open={open}
>
....
 <DialogActions>
    <Button onClick={handleClose} disabled={loading}>Cancel</Button>
 </DialogActions>
</Dialog>

1

只需在您的组件中添加“disableBackdropClick”属性。这将限制(禁用)弹出窗口或对话框之外的单击。

    //Example
    <DialogCss
      style={{ zIndex: 2000 }}
      open={ruleBoxOpen}
      keepMounted
      onClose={() => setRuleBoxOpen(false)}
      aria-labelledby="alert-dialog-slide-title"
      aria-describedby="alert-dialog-slide-description"
      disableBackdropClick
    >

1
如果点击对话框之外的背景,则不执行任何操作/不关闭对话框。确保过程正确完成。
const handleMeetingCreateDialogClose = (event, reason) => {
        if (reason && reason === "backdropClick")   return; 
        setFormData(formInitial);
        setMeetingCreateDialogOpen(false);
};

<Dialog open={meetingCreateDialogOpen} onClose={handleMeetingCreateDialogClose}  disableEscapeKeyDown  >

0
您可以创建一个类似的组件,就像这个一样:

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>
  );
}

希望这对你有所帮助!

0
这也是我的问题,似乎没有人回答得很好。这是我所做的。
包装器中删除onClose,即可能看起来像这样:
<Dialog
    sx={{
        position: 'absolute',
        left: 300,
        top: 35
    }}
    maxWidth="lg"
    open={open}
    // onClose={handleClose}      <<<<<<<
    ....
>

最后,将handleClose函数添加到close按钮的onClick事件中。
<Button
    color="primary"
    size="large"
    type="submit"
    variant="contained"
    onClick={handleClose}
>
    Close
</Button>

您的问题将会得到解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接