1

I'm tired to make a small list where the user can insert rows and clear a row also once the user submits then it should be visible to the same field.

Now I have faced two problems I can't delete an exact row when I clicked on the delete button the row deletes from the last, but I want it should be deleted exact row, that I want.

And another problem with my clear row button, once I clicked on that then it should be clear all rows without three buttons and a table head.

Here is my full code:

function Test2() {

  const [rows, setRows] = useState([]);

  // Initial states
  const [open, setOpen] = useState(false);
  const [isAdd, setAdd] = useState(false);
  const [disable, setDisable] = useState(true);
  const [showConfirm, setShowConfirm] = useState(false);

  const handleClose = (event, reason) => {
    if (reason === "clickaway") {
      return;
    }
    setOpen(false);
  };


  const handleAdd = () => {
    setRows([
      ...rows,
      {
        id: rows.length + 1,
        amount: "",
      },
    ]);
    setAdd(true);
  };

  // Function to handle save
  const handleSave = () => {
    setAdd(!isAdd);
    setRows(rows);
    // console.log("saved : ", rows);
    setDisable(true);
    setOpen(true);
    console.log(rows);
  };

  const handleInputChange = (e, index) => {
    setDisable(false);
    const { name, value } = e.target;
    const list = [...rows];
    list[index][name] = value;
    setRows(list);
  };

  const handleConfirm = () => {
    setShowConfirm(true);
  };


  const handleRemoveClick = (i) => {
    const list = [...rows];
    list.splice(i, 1);
    setRows(list);
    console.log(list);
    setShowConfirm(false);
  };

  // Handle the case of delete confirmation
  // where user click no
  const handleNo = () => {
    setShowConfirm(false);
  };

  const handleClearAll = () => {
    setAdd(false);
  };

  return (
    <div style={{ width: 600, margin: "auto" }}>
      <Button onClick={handleAdd}>
        <AddBoxIcon />
        INSERT NEW ROW
      </Button>
      <Button onClick={handleClearAll}>
        <ClearIcon /> CLEAR ROW
      </Button>

      {disable ? (
        <Button disabled align="right" onClick={handleSave}>
          <DoneIcon />
          SUBMIT
        </Button>
      ) : (
        <Button align="right" onClick={handleSave}>
          <DoneIcon />
          SUBMIT
        </Button>
      )}

      <Table>
        <TableHead>
          <TableRow>
            <TableCell>Item name </TableCell>
            <TableCell>Amount</TableCell>
            <TableCell>Action</TableCell>
          </TableRow>
        </TableHead>

        <TableBody>
          {rows?.map((row, i) => {
            return (
              <TableRow key={i}>
                {isAdd ? (
                  <TableCell>{`Item ${row.id}`}</TableCell>
                ) : (
                  <TableCell>{`Item ${row.id}`}</TableCell>
                )}
                {isAdd ? (
                  <TableCell align="left">
                    <TextField
                      sx={{
                        width: 100,
                      }}
                      type="number"
                      value={row.amount}
                      name="amount"
                      onChange={(e) => handleInputChange(e, i)}
                    />
                  </TableCell>
                ) : (
                  <TableCell>{row.amount}</TableCell>
                )}

                {isAdd ? (
                  <TableCell>
                    <Button className="mr10" onClick={handleConfirm}>
                      <ClearIcon />
                    </Button>
                  </TableCell>
                ) : (
                  <TableCell>
                    <Button className="mr10" onClick={handleConfirm}>
                      <DeleteOutlineIcon />
                    </Button>
                  </TableCell>
                )}
                {showConfirm && (
                  <div>
                    <Dialog open={showConfirm} onClose={handleNo}>
                      <DialogTitle id="alert-dialog-title">
                        {"Confirm Delete"}
                      </DialogTitle>
                      <DialogContent>
                        <DialogContentText id="alert-dialog-description">
                          Are you sure to delete
                        </DialogContentText>
                      </DialogContent>
                      <DialogActions>
                        <Button
                          onClick={() => handleRemoveClick(i)}
                          color="primary"
                          autoFocus
                        >
                          Yes
                        </Button>
                        <Button onClick={handleNo} color="primary" autoFocus>
                          No
                        </Button>
                      </DialogActions>
                    </Dialog>
                  </div>
                )}
              </TableRow>
            );
          })}

          <Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
            <Alert onClose={handleClose} severity="success">
              Record saved successfully!
            </Alert>
          </Snackbar>
        </TableBody>
      </Table>
    </div>
  );
}

export default Test2;
3
  • handleRemoveClick is it your clear row function? Commented Oct 13, 2022 at 4:44
  • Yes @Kiddo, but it delete from the last table data. Commented Oct 13, 2022 at 4:45
  • 1
    let removeData = rows.filter(el => el.id !== i) then setRows(removeData) . Commented Oct 13, 2022 at 4:48

1 Answer 1

1

Your problem is you're using i (index) which will be changed when you add/remove rows, so I'd suggest that you should use id (row id) instead

handleRemoveClick(row.id)

And then modify handleRemoveClick to

const handleRemoveClick = (rowId) => {
    const list = rows.filter(row => row.id !== rowId); //only remove the selected row
    setRows(list);
    setShowConfirm(false);
};

Along with that, you also need to make your row ids unique

const generateUniqueId = () => {  
  return 'xxxx-xxxx-xxx-xxxx'.replace(/[x]/g, (c) => {  
        const r = Math.floor(Math.random() * 16);  
        return r.toString(16);  
  });  
}

const handleAdd = () => {
    setRows([
      ...rows,
      {
        id: generateUniqueId(),
        amount: "",
      },
    ]);
    setAdd(true);
};

If you don't want to have a unique id generator, you have to modify all row ids

const handleRemoveClick = (rowId) => {
    let list = rows.filter(row => row.id !== rowId); //only remove the selected row
    list = list.map((row, index) => ({
       ...row,
       id: index //assign the new index for id
    }));
    setRows(list);
    setShowConfirm(false);
};

Side note, this way will re-render all rows that may cause some performance problems if you have too many rows to modify.


For your second problem to clear all rows, you should modify handleClearAll like below

const handleClearAll = () => {
    setAdd(false);
    setRows([]);//clear all rows
};
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you so much @Nick Vu, now I'm clear, actually, where did I mistake
bro, actually I don't want a unique id generator, I need to value starting from 1. Now I have to face another problem, I can't delete last table row, maybe it happened from id: rows.length + 1 here, do you have any idea! how to solved
which event do you use for the last row removal? it's still handleRemoveClick? @Alamin
Yes, it's from 'handleRemoveClick', supposed I added 3 row, after that I can easily remove 2 row, but last one can't remove.
I added the part you need into my answer, you can try it :D @Alamin

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.