【问题标题】:How to set row data when clicking button inside the row material-ui DataGrid?单击行材料-ui DataGrid内的按钮时如何设置行数据?
【发布时间】:2021-07-20 05:21:38
【问题描述】:

我有一个 Material-UI DataGrid 组件,它有一个连续的编辑和删除按钮,但我只能做警报或控制台日志,

为什么会有按钮在一行,因为点击按钮时需要对话框,例如当用户点击删除按钮时会有一个删除操作的确认对话框,或者当点击一个编辑按钮时会有一个表单对话框更新行,

需要推送用户同时只编辑或删除一项。所以不允许多选。

我的问题是如何在点击列定义内的按钮时获取组件中的行数据,在这种情况下,点击EditDelete按钮。

使用"@material-ui/data-grid": "^4.0.0-alpha.26"

import Container from "@material-ui/core/Container";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import DeleteIcon from "@material-ui/icons/Delete";
import EditIcon from "@material-ui/icons/Edit";
import Button from "@material-ui/core/Button";
import AddIcon from "@material-ui/icons/Add";
import { makeStyles } from "@material-ui/core/styles";
import {
  DataGrid,
  GridColDef,
  GridApi,
  GridCellValue
} from "@material-ui/data-grid";

const columns: GridColDef[] = [
  { field: "id", headerName: "ID", width: 70 },
  { field: "name", headerName: "First name", width: 130 },
  { field: "surname", headerName: "Last name", width: 130 },
  {
    field: "edit",
    headerName: "Edit",
    sortable: false,
    width: 130,
    disableClickEventBubbling: true,
    renderCell: (params) => {
      const onClick = () => {
        const api: GridApi = params.api;
        const fields = api
          .getAllColumns()
          .map((c) => c.field)
          .filter((c) => c !== "__check__" && !!c);
        const thisRow: Record<string, GridCellValue> = {};

        fields.forEach((f) => {
          thisRow[f] = params.getValue(f);
        });

        // set to state rather then alert
        return alert(JSON.stringify(thisRow, null, 4));
      };
      return (
        <Button
          variant="contained"
          color="primary"
          startIcon={<EditIcon />}
          onClick={onClick}
        >
          Edit
        </Button>
      );
    }
  },
  {
    field: "delete",
    headerName: "Delete",
    sortable: false,
    width: 130,
    disableClickEventBubbling: true,
    renderCell: (params) => {
      const onClick = () => {
        const api: GridApi = params.api;
        const fields = api
          .getAllColumns()
          .map((c) => c.field)
          .filter((c) => c !== "__check__" && !!c);
        const thisRow: Record<string, GridCellValue> = {};

        fields.forEach((f) => {
          thisRow[f] = params.getValue(f);
        });

        // set to state rather then alert
        return alert(JSON.stringify(thisRow, null, 4));
      };
      return (
        <Button
          variant="contained"
          color="secondary"
          startIcon={<DeleteIcon />}
          onClick={onClick}
        >
          Delete
        </Button>
      );
    }
  }
];

const rows = [
  { id: 1, name: "Example 1", surname: "example" },
  { id: 2, name: "Example 2", surname: "example" }
];

export type User = {
  id: number;
  name: string;
  surname: string;
};

const useStyles = makeStyles((theme) => ({
  content: {
    flexGrow: 1,
    height: "100vh",
    overflow: "auto"
  },
  appBarSpacer: theme.mixins.toolbar,
  container: {
    paddingTop: theme.spacing(4),
    paddingBottom: theme.spacing(4)
  },
  paper: {
    padding: theme.spacing(2),
    display: "flex",
    overflow: "auto",
    flexDirection: "column",
    elevation: 3
  }
}));

const App = () => {
  const classes = useStyles();

  return (
    <main className={classes.content}>
      <div className={classes.appBarSpacer} />
      <Container maxWidth="lg" className={classes.container}>
        <Grid item xs={12}>
          <Paper className={classes.paper}>
            <DataGrid
              rows={rows}
              columns={columns}
              pageSize={10}
              columnBuffer={8}
              autoHeight
            />
          </Paper>
        </Grid>
        <Grid item xs={3} style={{ padding: 20 }}>
          <Button
            variant="contained"
            color="primary"
            startIcon={<AddIcon />}
            onClick={() => {
              console.log("new");
            }}
          >
            New
          </Button>
        </Grid>
      </Container>
    </main>
  );
};

export default App;

【问题讨论】:

  • 我想知道Dialog组件在哪里。
  • 您没有在renderCell 中放置任何对话框组件。
  • @Medi 如果没有实现和按需显示/隐藏,就无法打开对话框。
  • 对不起,我稍后会添加对话框组件。但现在我只想设置状态,然后我可以将任何想要的组件传递给它。

标签: javascript reactjs material-ui


【解决方案1】:

DataGrid 组件有一个 prop onCellClick 来处理用户单击数据网格中的任何单元格时的事件。该道具使用GridCellParams类型,只需要根据GridCellParams.colDef.field属性过滤列即可。

代码修改如下;

编辑:根据Material-UI documentation,GridCellParams 属性getValue 刚刚更改。现在它需要两个参数; getValue(id: GridRowId, field: string)

import Container from "@material-ui/core/Container";
import Grid from "@material-ui/core/Grid";
import Paper from "@material-ui/core/Paper";
import DeleteIcon from "@material-ui/icons/Delete";
import EditIcon from "@material-ui/icons/Edit";
import Button from "@material-ui/core/Button";
import { makeStyles } from "@material-ui/core/styles";
import {
  DataGrid,
  GridColDef,
  GridApi,
  GridCellValue,
  GridCellParams
} from "@material-ui/data-grid";
import React, { useState } from "react";
import {
  Dialog,
  DialogTitle,
  DialogContent,
  DialogContentText,
  DialogActions
} from "@material-ui/core";

const columns: GridColDef[] = [
  { field: "id", headerName: "ID", width: 70 },
  { field: "name", headerName: "First name", width: 130 },
  { field: "surname", headerName: "Last name", width: 130 },
  {
    field: "edit",
    headerName: "Edit",
    sortable: false,
    width: 130,
    disableClickEventBubbling: true,
    renderCell: () => {
      return (
        <Button variant="contained" color="primary" startIcon={<EditIcon />}>
          Edit
        </Button>
      );
    }
  },
  {
    field: "delete",
    headerName: "Delete",
    sortable: false,
    width: 130,
    disableClickEventBubbling: true,
    renderCell: () => {
      return (
        <Button
          variant="contained"
          color="secondary"
          startIcon={<DeleteIcon />}
        >
          Delete
        </Button>
      );
    }
  }
];

const rows = [
  { id: 1, name: "Example 1", surname: "example" },
  { id: 2, name: "Example 2", surname: "example" }
];

export type User = {
  id: number;
  name: string;
  surname: string;
};

const useStyles = makeStyles((theme) => ({
  content: {
    flexGrow: 1,
    height: "100vh",
    overflow: "auto"
  },
  appBarSpacer: theme.mixins.toolbar,
  container: {
    paddingTop: theme.spacing(4),
    paddingBottom: theme.spacing(4)
  },
  paper: {
    padding: theme.spacing(2),
    display: "flex",
    overflow: "auto",
    flexDirection: "column",
    elevation: 3
  }
}));

const App = () => {
  const classes = useStyles();
  const [selectedUser, setSelectedUser] = useState({} as User);
  const [openDialog, setOpenDialog] = useState(false);

  function currentlySelected(params: GridCellParams) {
    const api: GridApi = params.api;
    const value = params.colDef.field;

    if (!(value === "edit" || value === "delete")) {
      return;
    }

    const fields = api
      .getAllColumns()
      .map((c) => c.field)
      .filter((c) => c !== "__check__" && !!c);
    const thisRow: Record<string, GridCellValue> = {};

    fields.forEach((f) => {
      thisRow[f] = params.getValue(params.id, f);
    });

    const user = {} as User;
    user["id"] = Number(thisRow["id"]);
    user["name"] = thisRow["name"]!.toString();
    user["surname"] = thisRow["surname"]!.toString();

    setSelectedUser(user);
    setOpenDialog(true);
  }

  const handleClose = () => {
    setOpenDialog(false);
  };

  return (
    <main className={classes.content}>
      <div className={classes.appBarSpacer} />
      <Container maxWidth="lg" className={classes.container}>
        <Grid item xs={12}>
          <Paper className={classes.paper}>
            <DataGrid
              rows={rows}
              columns={columns}
              pageSize={10}
              columnBuffer={8}
              autoHeight
              onCellClick={currentlySelected}
            />
          </Paper>
        </Grid>
      </Container>
      <Dialog
        open={openDialog}
        onClose={handleClose}
        aria-labelledby="form-dialog-title"
      >
        <DialogTitle id="form-dialog-title"> User </DialogTitle>
        <DialogContent>
          <DialogContentText id="alert-dialog-description">
            {JSON.stringify(selectedUser)}
          </DialogContentText>
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose} color="primary">
            Cancel
          </Button>
          <Button onClick={handleClose} color="primary">
            Confirm
          </Button>
        </DialogActions>
      </Dialog>
    </main>
  );
};

export default App;

【讨论】:

  • 更新您现有的问题。
  • 这是您问题的答案吗?
  • 是的,完全正确。你可能误解了这个问题。
  • 从打字稿中,我现在遇到了一些错误(06/08/2021)。也许这是一个过时的答案。
  • @hfontanez 我编辑了链接,现在可以使用了。
【解决方案2】:

更新 - 2021 年

06/08/2021 - 最新答案

以下内容按预期对我有用。

const columns: GridColDef[] = [
  { field: 'id', headerName: 'ID', width: 100, hide: true },
  {
    field: 'action',
    width: 130,
    sortable: false,

    renderCell: (params) => {
      const onClickDelete = async () => {
        return alert(JSON.stringify(params.row, null, 4));
      };
      const onClickEdit = async () => {};

      return (
        <>
          <IconButton color="secondary" onClick={onClickDelete}>
            <DeleteIcon />
          </IconButton>
          <IconButton color="secondary" onClick={onClickEdit}>
            <EditIcon />
          </IconButton>
        </>
      );
    },
  },

【讨论】:

    猜你喜欢
    • 2021-10-16
    • 2022-12-10
    • 2019-06-08
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 2019-02-19
    • 1970-01-01
    • 2021-07-16
    相关资源
    最近更新 更多