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;
CodePudding user response:
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
};