How to add a button to every row in MUI DataGrid

Viewed 48223

I cant add a button into every row of MUI DataGrid. I have a MUI DataGrid which I render like this:

<DataGrid rows={rows} columns={columns} pageSize={5} checkboxSelection />

I have added into the columns variable 'actions' column where the button should be. rows are just a a data object I get from the props. how can I add a button into every row (for editing the row)? I have tried mapping the data array but it is not possible to add JSX button into every object of data.

3 Answers

You can add your custom component by overriding GridColDef.renderCell method and return whatever element you want.

The example below displays an action column that renders a single button in each row. When clicking the button, it alerts the current row data in json string:

const columns: GridColDef[] = [
  { field: "id", headerName: "ID", width: 70 },
  {
    field: "action",
    headerName: "Action",
    sortable: false,
    renderCell: (params) => {
      const onClick = (e) => {
        e.stopPropagation(); // don't select this row after clicking

        const api: GridApi = params.api;
        const thisRow: Record<string, GridCellValue> = {};

        api
          .getAllColumns()
          .filter((c) => c.field !== "__check__" && !!c)
          .forEach(
            (c) => (thisRow[c.field] = params.getValue(params.id, c.field))
          );

        return alert(JSON.stringify(thisRow, null, 4));
      };

      return <Button onClick={onClick}>Click</Button>;
    }
  },
];

Edit 64331095/cant-add-a-button-to-every-row-in-material-ui-table

Just came across this.

What you need to do is include a renderCell method in your columns array.

 const columns = [
    {
        field: 'col1',
        headerName: 'Name 1',
        width: 150,
        disableClickEventBubbling: true,
    },
    {
        field: 'col2',
        headerName: 'Name 2',
        width: 300,
        disableClickEventBubbling: true,
    },
    {
        field: 'col3',
        headerName: 'Name 3',
        width: 300,
        disableClickEventBubbling: true,
    },
    {
        field: 'col4',
        headerName: 'Name 4',
        width: 100,
        disableClickEventBubbling: true,
    },
    {
        field: 'col5',
        headerName: 'Name 5',
        width: 150,
        ***renderCell: renderSummaryDownloadButton,***
        disableClickEventBubbling: true,
    },
    {
        field: 'col6',
        headerName: 'Name 6',
        width: 150,
        ***renderCell: renderDetailsButton,***
        disableClickEventBubbling: true,
    },
]

In the above I am rendering a Button inside columns 5 and 6 which will appear on every populated row.

Above that you can have a function which creates and returns a Button from Material-ui.

 const renderDetailsButton = (params) => {
        return (
            <strong>
                <Button
                    variant="contained"
                    color="primary"
                    size="small"
                    style={{ marginLeft: 16 }}
                    onClick={() => {
                        parseName(params.row.col6)
                    }}
                >
                    More Info
                </Button>
            </strong>
        )
    }

While @NearHuscarl's response answers the question perfectly, I'd like to post a TypeScript example:

  const onClick = () => {
    const api: GridApi = params.api;
    const fields = api
      .getAllColumns()
      .map((c) => c.field)
      .filter((c) => c !== "__check__" && !!c);
    const thisRow: any = {};

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

    return alert(JSON.stringify(thisRow, null, 4));
  };

  return <Button onClick={onClick}>Click</Button>;

Also note, I changed the getValue call. (included the row id)

Related