javascriptreactjsmaterial-uidatagridmui-x-data-grid

How to get the updated value of a particular cell in MUI X Data Grid


When I updated the cell in the data grid, I was only able to retrieve the ID and field through the prop selectedCellParams here but I could not get its modified value.

I want to get the selected value inside the handleSaveOrEdit() function in order to accomplish the PUT request to update the API. How to use the getValue as given in the MUI Docs.

The entire code is below;

import * as React from 'react';
import PropTypes from 'prop-types';
import { Typography, Grid } from "@mui/material";
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import { DataGrid, GridCellModes } from '@mui/x-data-grid';
import { styled } from '@mui/material/styles';
import { useState, useEffect } from "react";
import Avatar from "@mui/material/Avatar";
import axios from 'axios';

const DrawerHeader = styled('div')(({ theme }) => ({
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 1),
    ...theme.mixins.toolbar,
}));

function EditToolbar(props) {
    const { selectedCellParams, cellMode, cellModesModel, setCellModesModel } = props;

    const handleSaveOrEdit = () => {
        if (!selectedCellParams) {
            return;
        }
        const { id, field } = selectedCellParams;
        if (cellMode === 'edit') {
            setCellModesModel({
                ...cellModesModel,
                [id]: { ...cellModesModel[id], [field]: { mode: GridCellModes.View } },
            });
            
            const getValue = (params) => console.log(params.value);
            console.log('value:::', getValue);

        } else {
            setCellModesModel({
                ...cellModesModel,
                [id]: { ...cellModesModel[id], [field]: { mode: GridCellModes.Edit } },
            });
        }
    };

    const handleCancel = () => {
        if (!selectedCellParams) {
            return;
        }
        const { id, field } = selectedCellParams;
        setCellModesModel({
            ...cellModesModel,
            [id]: {
                ...cellModesModel[id],
                [field]: { mode: GridCellModes.View, ignoreModifications: true },
            },
        });
    };

    const handleMouseDown = (event) => {
        // Keep the focus in the cell
        event.preventDefault();
    };

    return (
        <Box
            sx={{
                borderBottom: 1,
                borderColor: 'divider',
                p: 1,
            }}
        >
            <Button
                onClick={handleSaveOrEdit}
                onMouseDown={handleMouseDown}
                disabled={!selectedCellParams}
                color="primary"
                variant="outlined"
            >
                {cellMode === 'edit' ? 'Save' : 'Edit'}
            </Button>
            <Button
                onClick={handleCancel}
                onMouseDown={handleMouseDown}
                disabled={cellMode === 'view'}
                color="primary"
                variant="outlined"
                sx={{ ml: 1 }}
            >
                Cancel
            </Button>
        </Box>
    );
}

EditToolbar.propTypes = {
    cellMode: PropTypes.oneOf(['edit', 'view']).isRequired,
    cellModesModel: PropTypes.object.isRequired,
    selectedCellParams: PropTypes.shape({
        field: PropTypes.string.isRequired,
        id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
    }),
    setCellModesModel: PropTypes.func.isRequired,
};

export default function Donees() {
    const [selectedCellParams, setSelectedCellParams] = React.useState(null);
    const [cellModesModel, setCellModesModel] = React.useState({});

    const [tableData, setTableData] = useState([])
    const [fname, setFname] = useState("");
    const [lname, setLname] = useState("");
    const [address, setAddress] = useState("");
    const [dob, setDob] = useState("");
    const [gender, setGender] = useState("");
    const [email, setEmail] = useState("");
    const [phone, setPhone] = useState("");
    const [grade, setGrade] = useState("");
    const [photo, setPhoto] = useState("");

    useEffect(() => {
        fetch("http://localhost:4000/donees")
            .then((data) => data.json())
            .then((data) => setTableData(data))

    }, [])

    useEffect(() => {
        axios.get("http://localhost:4000/donees")
            .then((response) => {
                setFname(response.data.fname);
                setLname(response.data.lname);
                setAddress(response.data.address);
                setDob(response.data.dob);
                setGender(response.data.gender);
                setEmail(response.data.email);
                setPhone(response.data.phone);
                setGrade(response.data.grade);
                setPhoto(response.data.photo);
            })
    }, [])

    // console.log(tableData);

    const handleCellFocus = React.useCallback((event) => {
        const row = event.currentTarget.parentElement;
        const id = row.dataset.id;
        const field = event.currentTarget.dataset.field;
        setSelectedCellParams({ id, field });
    }, []);

    const cellMode = React.useMemo(() => {
        if (!selectedCellParams) {
            return 'view';
        }
        const { id, field } = selectedCellParams;
        return cellModesModel[id]?.[field]?.mode || 'view';
    }, [cellModesModel, selectedCellParams]);

    const handleCellKeyDown = React.useCallback(
        (params, event) => {
            if (cellMode === 'edit') {
                // Prevents calling event.preventDefault() if Tab is pressed on a cell in edit mode
                event.defaultMuiPrevented = true;
            }
        },
        [cellMode],
    );

    return (
        <Box component="main">
            <DrawerHeader />
            <Typography sx={{ textAlign: "center", pt: 5 }} variant="h5">Donees Table</Typography>
            <Grid container spacing={3} sx={{ pl: 15, pr: 15, pt: 5 }}>
                <div style={{ height: 400, width: '100%' }}>
                    <DataGrid
                        rows={tableData}
                        columns={columns}
                        getRowId={(row) => row._id}
                        onCellKeyDown={handleCellKeyDown}
                        cellModesModel={cellModesModel}
                        components={{
                            Toolbar: EditToolbar,
                        }}
                        componentsProps={{
                            toolbar: {
                                cellMode,
                                selectedCellParams,
                                setSelectedCellParams,
                                cellModesModel,
                                setCellModesModel,
                            },
                            cell: {
                                onFocus: handleCellFocus,
                            },
                        }}
                        experimentalFeatures={{ newEditingApi: true }}
                    />
                </div>
            </Grid>
        </Box>
    );
}

const columns = [
    { field: 'fname', headerName: 'First Name', width: 140, editable: true },
    { field: 'lname', headerName: 'Last Name', width: 140, editable: true },
    { field: 'address', headerName: 'Address', width: 200, editable: true },
    { field: 'dob', headerName: 'Date of Birth', width: 140, editable: true },
    { field: 'gender', headerName: 'Gender', width: 100, editable: true },
    { field: 'email', headerName: 'Email ID', width: 140, editable: true },
    { field: 'phone', headerName: 'Mobile Number', type: 'number', width: 140, editable: true },
    { field: 'grade', headerName: 'Grade', width: 180, editable: true },
    {
        field: 'photo', headerName: 'Photo', width: 180, editable: true, renderCell: (params) => {
            // console.log(params);
            return (
                <>
                    <Avatar src={params.value} />
                </>
            );
        }
    },
];


Solution

  • add following to dataGrid

    <DataGrid   
    processRowUpdate={processRowUpdate}
    />
    

    add

     const processRowUpdate = (newRow: any) => {
        const updatedRow = { ...newRow, isNew: false };
        console.log(updatedRow);
        //handle send data to api
        return updatedRow;
      };