Home > Mobile >  How can I update only a single cell value and json in table
How can I update only a single cell value and json in table

Time:04-24

I'm writing a code where I have a table of 3 columns. the last column is editable. My requirement is, when I click on that cell, add a new value, and it should update the corresponding value in the JSON.

Currently, I'm

  1. Unable to enter a value in the cell (though it is editable).
  2. Unable to know how I can update the json.

Here is my code.

import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import { useEffect } from "react";
const csvArray = [
  { Name: "user 1", Age: "12", Rank: "2" },
  { Name: "user 2", Age: "13", Rank: "3" },
  { Name: "user 3", Age: "10", Rank: "2" },
  { Name: "user 4", Age: "16", Rank: "1" },
  { Name: "user 5", Age: "14", Rank: "5" }
];
const keys = ["Name", "Age", "Rank"];
const RenderTable = () => {
  const handleBlur = (e) => {
    e.currentTarget.classList.add("noBorder");
    e.currentTarget.classList.remove("border");
  };

  useEffect(() => {
    console.log(JSON.stringify(csvArray));
  }, []);

  const handleChange = (e) => {
    e.currentTarget.readOnly = false;
    e.currentTarget.classList.remove("noBorder");
    e.currentTarget.classList.add("border");
    e.preventDefault();
  };

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            {keys.map((item, idx) => (
              <TableCell key={idx}>{item}</TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {csvArray.map((item, idx) => (
            <TableRow>
              {keys.map((key, idx) =>
                key === "Rank" ? (
                  <TableCell>
                    <input
                      
                      type="true"
                      readOnly="true"
                      value={item[key]}
                      onBlur={(e) => handleBlur(e)}
                      onClick={(e) => handleChange(e)}
                    ></input>
                  </TableCell>
                ) : (
                  <TableCell> {item[key]} </TableCell>
                )
              )}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default RenderTable;

Here it is in action https://codesandbox.io/s/wandering-pine-pddi4l?file=/src/RenderTable.js:0-2161. Please lemme know where I'm going wrong and how I can fix this.

CodePudding user response:

I've added csvArrayState state to control change. The issue you're having pertains to control. Yes you did change the type and made ranks editable but you lacked control. This snippet adds that control.

import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import { useState } from "react";
const csvArray = [
  { Name: "user 1", Age: "12", Rank: "2" },
  { Name: "user 2", Age: "13", Rank: "3" },
  { Name: "user 3", Age: "10", Rank: "2" },
  { Name: "user 4", Age: "16", Rank: "1" },
  { Name: "user 5", Age: "14", Rank: "5" }
];
const keys = ["Name", "Age", "Rank"];
const RenderTable = () => {

  const [csvArrayState, setCsvArrayState] = useState(() => 
    csvArray);

  const handleBlur = (e) => {
    e.currentTarget.classList.add("noBorder");
    e.currentTarget.classList.remove("border");
    console.log(JSON.stringify(csvArrayState));
  };

  const handleChange = (e) => {
    e.preventDefault();
    e.currentTarget.readOnly = false;
    e.currentTarget.classList.remove("noBorder");
    e.currentTarget.classList.add("border");
  };

  return (
    <TableContainer component={Paper}>
      <Table sx={{ minWidth: 650 }} aria-label="simple table">
        <TableHead>
          <TableRow>
            {keys.map((item, idx) => (
              <TableCell key={idx}>{item}</TableCell>
            ))}
          </TableRow>
        </TableHead>
        <TableBody>
          {csvArray.map((item, i) => (
            <TableRow>
              {keys.map((key, idx) =>
                key === "Rank" ? (
                  <TableCell>
                    <input
                      
                      type="true"
                      readOnly="true"
                      value={csvArrayState[i].Rank}
                      onChange={(e) => {
                        const updatedRankFields = csvArrayState.map((r, rIdx) => {
                          if (rIdx === i) {
                            return { ...r, Rank: e.target.value };
                          } else {
                            return r;
                          }
                        });
                        setCsvArrayState(updatedRankFields);
                      }}
                      onBlur={(e) => handleBlur(e)}
                      onClick={(e) => handleChange(e)}
                    ></input>
                  </TableCell>
                ) : (
                  <TableCell> {item[key]} </TableCell>
                )
              )}
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default RenderTable;
  • Related