单击行材料-ui DataGrid内的按钮时如何设置行数据?

Posted

技术标签:

【中文标题】单击行材料-ui DataGrid内的按钮时如何设置行数据?【英文标题】:How to set row data when clicking button inside the row material-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 如果没有实现和按需显示/隐藏,就无法打开对话框。 对不起,我稍后会添加对话框组件。但现在我只想设置状态,然后我可以将任何想要的组件传递给它。 【参考方案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>
        </>
      );
    ,
  ,

【讨论】:

以上是关于单击行材料-ui DataGrid内的按钮时如何设置行数据?的主要内容,如果未能解决你的问题,请参考以下文章

材料ui datagrid复选框行选择不起作用

如何动态设置DataGrid中某些行的选中状态

如何使用reactjs和material ui删除表格内的特定文本字段

单击 TemplateColumn 按钮上的访问 Datagrid 行

更新 AJAX 手风琴内的 DataGrid

wpf datagrid 单元格如何默认单击一次点中