reactjsmaterial-uimui-x-data-grid

How do I change state of MUI X Data Grid when using a checkbox in cellRender?


So I have a fairly simple scenario I'm working with where I need a checkbox in a MUI X Data Grid, but not using checkboxSelection. It's easy enough for me to render my checkbox in a column, but I can't really figure out how to change the state of that grid row once I check the box. The function receives the event object and you can access the target element, but I'm trying to actually change the value of the confirmed property on the row.

Here's the sample code for the component.

import React, { useState, useEffect } from 'react'
import { Checkbox } from '@mui/material';
import { DataGrid } from '@mui/x-data-grid'

const DataTable = () => {

    const [tableData, setTableData] = useState([])

    function handleConfirmChange() {
      console.log('How do I change row state here????');
    }

    const columns = [
      { field: 'title', headerName: 'Title', width: 200 },
      { field: 'body', headerName: 'Body', width: 600 },
      {
        field: 'confirmed',
        headerName: 'Confirmed',
        renderCell: (params) => (
          <Checkbox
            checked={params.confirmed===1}
            onChange={handleConfirmChange}
          />
        ),
      }
    ]

    useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts")
          .then((data) => data.json())
          .then((data) => {
            for (var i=0; i<data.length; i++) {
              data[i].confirmed = false;
            }
            setTableData(data);
          })
    
      }, [])

  return (
    <div style={{ height: 700, width: '100%' }}>
      <DataGrid
        rows={tableData}
        columns={columns}
        pageSize={12}
      />
    </div>
  )
}

export default DataTable

Solution

  • In the checked={params.confirmed===1} statement, the confirmed in the params property is not the property from the tableData. It is the columns' field name.

    To get the clicked row, we have to set Id for each row, pass the rowId as param from the checkbox, then we can identify the clicked row.

    So, in the useEffect hook, we have to set the rowId based on the index.

    useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts")
          .then((data) => data.json())
          .then((data) => {
            setTableData(
              data.map((x, index) => ({
                ...x,
                rowId: index,
                confirmed: false
              }))
            );
          });
      }, []);
    

    Then pass the row as param in the checkbox click event. Also, set the checked property as params.rows?.confirmed. The params.rows gives the actual row data. The rows maybe null during the initialization, so we have to set Optional chaining (?.) to the confirmed property.

     <Checkbox
       checked={params.rows?.confirmed}
       onChange={() => handleConfirmChange(params.row)}
     />
    

    In the handleConfirmChange function, get the clicked row and update the confirmed property. Loop through the tableData array and get the clicked row, then set the confirmed and update the grid.

    function handleConfirmChange(clickedRow) {
    const updatedData = tableData.map((x) => {
      if (x.rowId === clickedRow.rowId) {
        return {
          ...x,
          confirmed: !clickedRow.confirmed
        };
      }
      return x;
    });
    setTableData(updatedData);
    

    }

    Here is the updated working code and codesandbox.

    import React, { useState, useEffect } from "react";
    import { Checkbox } from "@mui/material";
    import { DataGrid } from "@mui/x-data-grid";
    
    export default function DataTable() {
      const [tableData, setTableData] = useState([]);
    
      function handleConfirmChange(clickedRow) {
        const updatedData = tableData.map((x) => {
          if (x.rowId === clickedRow) {
            return {
              ...x,
              confirmed: true
            };
          }
          return x;
        });
        setTableData(updatedData);
      }
    
      const columns = [
        { field: "title", headerName: "Title", width: 200 },
        { field: "body", headerName: "Body", width: 400 },
        {
          field: "confirmed",
          headerName: "Confirmed",
          renderCell: (params) => (
            <Checkbox
              checked={params.rows?.confirmed}
              onChange={() => handleConfirmChange(params.row.rowId)}
            />
          )
        }
      ];
    
      useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/posts")
          .then((data) => data.json())
          .then((data) => {
            setTableData(
              data.map((x, index) => ({
                ...x,
                rowId: index,
                confirmed: false
              }))
            );
          });
      }, []);
    
      return (
        <div style={{ height: 400, width: "100%" }}>
          <DataGrid
            rows={tableData}
            columns={columns}
            pageSize={12}
            rowsPerPageOptions={[12]}
          />
        </div>
      );
    }
    

    Edit SOQ-71445011-MUI-DataGrid