You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击MUI X Data Grid行内按钮触发MUI Modal的实现方案

在MUI X Data Grid行内按钮点击时打开MUI Modal的实现方案

我已经实现了带有操作按钮的MUI X Data Grid组件,现在需要实现点击每行的Delete按钮时,弹出包含该行详情的MUI Modal,并且在Modal中添加按钮向服务器发送删除请求。现有DataGrid组件和Modal组件代码如下:

原UserDataGrid组件代码

function UserDataGrid() {
  const { allUsers, filteredUsers, setFilteredUsers, traffics } =
    useContext(UserContext);

  const handleEvent = (e) => {
    console.log(e.field);
  };

  const columns = [
    { field: "id", headerName: "ای دی" },
    { field: "username", headerName: "یوزر" },
    {
      field: "enable",
      headerName: "وضعیت",
      type: "boolean",
      width: 140,
      editable: true,
      renderCell: (params) => {
        return params.value ? <p>فعال</p> : <p>غیر فعال</p>;
      },
    },
    { field: "startdate", headerName: "تاریخ شروع", headerAlign: "center" },
    { field: "finishdate", headerName: "تاریخ پایان" },
    { field: "mobile", headerName: "موبایل" },
    { field: "referral", headerName: "معرف" },
    { field: "traffic", headerName: "ترافیک" },
    {
      field: "action",
      headerName: "Action",
      width: 180,
      sortable: false,
      disableClickEventBubbling: true,

      renderCell: (params) => {
        const onClick = (e) => {
          const currentRow = params.row;
          return alert(JSON.stringify(currentRow, null, 4));
        };

        return (
          <div direction="row" spacing={2}>
            <Button onClick={onClick}>Delete</Button>
            <Button onClick={onClick}>Edit</Button>
          </div>
        );
      },
    },
  ];

  return (
    <div>
      <DataGrid
        rows={allUsers}
        columns={columns}
        loading={!allUsers.length}
        onCellClick={handleEvent}
      />
    </div>
  );
}

export default UserDataGrid;

原DeleteModal组件代码

export default function DeleteModal() {
  const [open, setOpen] = React.useState(false);
  const handleOpen = () => setOpen(true);
  const handleClose = () => setOpen(false);

  return (
    <div>
      <Button onClick={handleOpen}>Open modal</Button>
      <Modal
        open={open}
        onClose={handleClose}
        aria-labelledby="modal-modal-title"
        aria-describedby="modal-modal-description"
      >
        <Box sx={style}>
          <Typography id="modal-modal-title" variant="h6" component="h2">
            Text in a modal
          </Typography>
          <Typography id="modal-modal-description" sx={{ mt: 2 }}>
            Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
          </Typography>
        </Box>
      </Modal>
    </div>
  );
}

实现步骤

  • 状态提升:把Modal的open状态和控制函数移到UserDataGrid组件中,同时新增状态存储当前点击的行数据,实现行内按钮对Modal的控制和数据传递。
  • 改造Modal组件:让DeleteModal接收open、handleClose、currentRow、handleDelete四个props,成为受控组件,专注于渲染内容和触发删除逻辑。
  • 修改行内按钮事件:在DataGrid的action列中,给Delete按钮绑定打开Modal的事件,传入当前行数据。
  • 添加请求逻辑:在Modal中添加确认删除按钮,调用接口完成删除操作。

修改后的完整代码

DeleteModal组件

import React from 'react';
import { Modal, Box, Typography, Button } from '@mui/material';

const style = {
  position: 'absolute',
  top: '50%',
  left: '50%',
  transform: 'translate(-50%, -50%)',
  width: 400,
  bgcolor: 'background.paper',
  border: '2px solid #000',
  boxShadow: 24,
  p: 4,
};

export default function DeleteModal({ open, handleClose, currentRow, handleDelete }) {
  if (!currentRow) return null;

  return (
    <Modal
      open={open}
      onClose={handleClose}
      aria-labelledby="modal-modal-title"
      aria-describedby="modal-modal-description"
    >
      <Box sx={style}>
        <Typography id="modal-modal-title" variant="h6" component="h2">
          删除用户确认
        </Typography>
        <Typography id="modal-modal-description" sx={{ mt: 2 }}>
          确定要删除用户 <strong>{currentRow.username}</strong> 吗?
        </Typography>
        <Typography sx={{ mt: 2 }}>
          用户ID: {currentRow.id}
          <br />
          手机号: {currentRow.mobile}
        </Typography>
        <Box sx={{ mt: 3, display: 'flex', justifyContent: 'flex-end', gap: 2 }}>
          <Button onClick={handleClose}>取消</Button>
          <Button variant="contained" color="error" onClick={() => handleDelete(currentRow.id)}>
            确认删除
          </Button>
        </Box>
      </Box>
    </Modal>
  );
}

UserDataGrid组件

import React, { useState } from 'react';
import { DataGrid, Button } from '@mui/x-data-grid';
import { useContext } from 'react';
import UserContext from './UserContext'; // 请根据实际路径调整
import DeleteModal from './DeleteModal'; // 请根据实际路径调整

function UserDataGrid() {
  const { allUsers } = useContext(UserContext);
  const [modalOpen, setModalOpen] = useState(false);
  const [currentRowData, setCurrentRowData] = useState(null);

  // 替换为实际的删除接口调用逻辑
  const handleDeleteUser = async (userId) => {
    try {
      // 示例接口请求:await fetch(`/api/users/${userId}`, { method: 'DELETE' });
      console.log(`删除用户ID: ${userId}`);
      // 删除成功后可更新表格数据,例如从allUsers中移除对应行
      handleCloseModal();
    } catch (error) {
      console.error('删除失败:', error);
    }
  };

  const handleOpenModal = (row) => {
    setCurrentRowData(row);
    setModalOpen(true);
  };

  const handleCloseModal = () => {
    setModalOpen(false);
    setCurrentRowData(null);
  };

  const columns = [
    { field: "id", headerName: "ای دی" },
    { field: "username", headerName: "یوزر" },
    {
      field: "enable",
      headerName: "وضعیت",
      type: "boolean",
      width: 140,
      editable: true,
      renderCell: (params) => {
        return params.value ? <p>فعال</p> : <p>غیر فعال</p>;
      },
    },
    { field: "startdate", headerName: "تاریخ شروع", headerAlign: "center" },
    { field: "finishdate", headerName: "تاریخ پایان" },
    { field: "mobile", headerName: "موبایل" },
    { field: "referral", headerName: "معرف" },
    { field: "traffic", headerName: "ترافیک" },
    {
      field: "action",
      headerName: "Action",
      width: 180,
      sortable: false,
      disableClickEventBubbling: true,
      renderCell: (params) => {
        return (
          <div style={{ display: 'flex', gap: 10 }}>
            <Button 
              variant="contained" 
              color="error"
              onClick={() => handleOpenModal(params.row)}
            >
              Delete
            </Button>
            <Button variant="outlined">Edit</Button>
          </div>
        );
      },
    },
  ];

  return (
    <div>
      <DataGrid
        rows={allUsers}
        columns={columns}
        loading={!allUsers.length}
      />
      <DeleteModal 
        open={modalOpen}
        handleClose={handleCloseModal}
        currentRow={currentRowData}
        handleDelete={handleDeleteUser}
      />
    </div>
  );
}

export default UserDataGrid;

关键说明

  • 状态提升后,UserDataGrid完全控制Modal的显示状态和当前行数据,避免组件间状态不同步问题。
  • DeleteModal作为受控组件,只负责渲染内容和触发删除回调,逻辑解耦更清晰。
  • 行内按钮通过handleOpenModal直接传递当前行数据,确保Modal能展示正确的用户详情。
  • handleDeleteUser函数可替换为实际的API请求,完成后关闭Modal并更新表格数据。

内容的提问来源于stack exchange,提问作者rasool bagheri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 16:03:18