最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to set row data when clicking button inside the row material-ui DataGrid? - Stack Overflow

programmeradmin2浏览0评论

I have a Material-UI DataGrid ponent that has edit and delete buttons in a row, but I can only do alert or console log,

Why there are buttons in a row because need dialogs when clicking the button, for example when the user clicks the delete button there will be a confirm dialog for delete action, or when click an edit button there will be a form dialog that updates the row,

Need to push the user to edit or delete only one item at the same time. So multiple selection is not allowed.

My question is how to get the row data in the ponent when clicking the button inside the column definition, in that case, click the Edit or Delete button.

Using "@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;

I have a Material-UI DataGrid ponent that has edit and delete buttons in a row, but I can only do alert or console log,

Why there are buttons in a row because need dialogs when clicking the button, for example when the user clicks the delete button there will be a confirm dialog for delete action, or when click an edit button there will be a form dialog that updates the row,

Need to push the user to edit or delete only one item at the same time. So multiple selection is not allowed.

My question is how to get the row data in the ponent when clicking the button inside the column definition, in that case, click the Edit or Delete button.

Using "@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;

Share Improve this question edited May 1, 2021 at 7:39 fuat asked Apr 26, 2021 at 20:25 fuatfuat 1,8722 gold badges21 silver badges28 bronze badges 4
  • I wonder where is Dialog ponent. – Marios Nikolaou Commented Apr 26, 2021 at 20:48
  • You arent placing any dialog ponent in the renderCell. – Medi Commented Apr 26, 2021 at 20:48
  • @Medi it's impossible to open a dialog without having the implementation and display/hide on demand. – Marios Nikolaou Commented Apr 26, 2021 at 20:53
  • Sorry I will add later the dialog ponent. But now I just want to set the state then I can pass it any ponent that desired. – fuat Commented Apr 26, 2021 at 20:57
Add a ment  | 

2 Answers 2

Reset to default 2

DataGrid ponent has a prop onCellClick to handle event when user clicks any cell in the data grid. This prop use GridCellParams type, just need to filter columns base on GridCellParams.colDef.field attribute.

Code changed as below;

EDIT: According to the Material-UI documentation, GridCellParams property getValue just changed. Now it takes two-parameter; 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;

Update - 2021

06/08/2021 - Latest answer

The following ones work for me as expected.

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>
        </>
      );
    },
  },
发布评论

评论列表(0)

  1. 暂无评论