Reputation: 1640
I want to make the row icon I click collapsible and display data. Presently if any of the row in table is clicked, it displays the collapsible content for all the rows.
{data.map((dataRow) => (
<TableRow
key={dataRow.id}
title="tableRow"
className={classes.tableRow}
>
<TableCell className={classes.tableCell}>
<IconButton size="small" onClick={() => setOpen(!open)}>
{open ? <ArrowDropDownIcon /> : <ArrowDropUpIcon />}
</IconButton>
{dataRow.id}
<Collapse in={open} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
</Box>
</Collapse>
</TableCell>
<TableCell className={classes.tableCell}>
{dataRow.name}
</TableCell>
<TableCell align="left" className={classes.tableCell}>
{dataRow.lastName}
</TableCell>
</TableRow>
))}
</TableBody>
Upvotes: 1
Views: 431
Reputation: 1640
This does not work. Any suggestions on what could be the error here : Thanks
const [openRows, setOpenRows] = useState<Record<string, boolean>>({});
const toggleRow = (dataRow: any) =>
setOpenRows((prevState) => ({
...prevState,
[dataRow.overrideTicketNumber]: true,
}));
<IconButton
size="small"
onClick={() => toggleRow(dataRow.overrideTicketNumber)}
>
{openRows ? <ArrowDropDownIcon /> : <ArrowDropUpIcon />}
</IconButton>
<Collapse
in={openRows[dataRow.overrideTicketNumber] ?? false}
timeout="auto"
unmountOnExit
>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
{dataRow.overrideTicketNumber}
</Typography>
</Box>
</Collapse>
</TableCell>
Upvotes: 0
Reputation: 1797
You can change the state variable open
from a boolean value to an object that keeps track of the open/closed state of all rows:
const [openRows, setOpenRows] = useState({});
const toggleRow = (rowId) =>
setOpenRows((previous) => ({
...previous,
[rowId]: !(previous[rowId] ?? false),
}));
return (
<TableBody>
{data.map((dataRow) => (
<TableRow key={dataRow.id} title="tableRow" className={classes.tableRow}>
<TableCell className={classes.tableCell}>
<IconButton size="small" onClick={() => toggleRow(dataRow.id)}>
{open ? <ArrowDropDownIcon /> : <ArrowDropUpIcon />}
</IconButton>
{dataRow.id}
<Collapse in={openRows[dataRow.id] ?? false} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
</Box>
</Collapse>
</TableCell>
<TableCell className={classes.tableCell}>{dataRow.name}</TableCell>
<TableCell align="left" className={classes.tableCell}>
{dataRow.lastName}
</TableCell>
</TableRow>
))}
</TableBody>
);
Upvotes: 0
Reputation: 629
You have one state variable "open" that is used in every row to determine if it is collapsed or not. So, all the rows are collapsed or all of them are open.
To open them one by one you need a separate state variable for each of the rows. You can create something like this:
const [openRows, setOpenRows] = useState({});
the keys in this object will be dataRow.id, and the values - boolean
So, when you need to open a specific row you call setOpenRows like this:
setOpenRows((prevState) => {
return { ...prevState, [dataRow.id]: true }
});
or with [dataRow.id]: false when you need to close it
And you pass the new value to Collapse component
<Collapse in={openRows[dataRow.id]} timeout="auto" unmountOnExit>
Upvotes: 1