PaulPolon
PaulPolon

Reputation: 329

Collapsing Table Row Collapses all Rows

I have a state to check if collapse is true or false

const [open, setOpen] = useState(false);

then returns on render:

<TableBody> {isCityReady && cities ? (cities.map((row, index) => (
<TableRow key={index} sx={{ borderBottom: "2px solid black", "&:last-child td, &:last-child th": { border: 0 } }}>
    <TableCell>
        <IconButton
        aria-label="expand row"
        size="small"
        onClick={() => setOpen(!open)}
        >
            {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
        </IconButton>
    </TableCell>
    <TableCell component="th" scope="row" align="left">
        <Typography variant="body1" fontWeight="bold">
            {row.city}
        </Typography>
    </TableCell>
    <TableCell>
        <Collapse in={open} timeout="auto" unmountOnExit>
            <Typography variant="body1" fontWeight="bold"> 
            {isReady && locations ? (locations.filter(rowLocation => rowLocation.city === row.city).map((rowLocation, indexLocation) => (
                <TableRow key={indexLocation} sx={{ "&:last-child td, &:last-child th": { border: 0 } }}>
                    <TableCell style={{ width: '100%' }}>
                        <Typography variant="body1">
                            {rowLocation.office}
                        </Typography>
                    </TableCell>
                    <TableCell align="right" style={{ width: '100%' }}>
                        <Button variant="contained" color="primary" onClick={() => handleOpenLocationsDialog("Edit", rowLocation.city, rowLocation.office, rowLocation.id)}>
                            Edit
                        </Button>
                    </TableCell>
                </TableRow>
            ))) : (<LocationsTableSkeleton />)}
            </Typography>
        </Collapse>
    </TableCell>
</TableRow>
))
) : (
    <LocationsTableSkeleton />
)}

every row would collapse/uncollapse simultanously. How do I make it so that only the row that was clicked would collpase?

Upvotes: 2

Views: 376

Answers (1)

Gabriele Petrioli
Gabriele Petrioli

Reputation: 195982

You need to keep a flag for each row.

something like the following

const [openCities, setOpenCities] = useState({});
const toggleCity = useCallback((city)=>{
  setOpenCities(state => ({
    ...state,
    [city]: !Boolean(state[city])
  }));
},[]);

then returns on render:

<TableBody> {isCityReady && cities ? (cities.map((row, index) => { 
// extract the flag/state of the specific city
const open = Boolean(openCities[row.city]);

return (
  <TableRow key={index} sx={{ borderBottom: "2px solid black", "&:last-child td, &:last-child th": { border: 0 } }}>
    <TableCell>
        <IconButton
        aria-label="expand row"
        size="small"
        onClick={() => toggleCity(row.city)}
        >
            {open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
        </IconButton>
    </TableCell>
    ......
    <TableCell>
        <Collapse in={open} timeout="auto" unmountOnExit>
       .....

Upvotes: 1

Related Questions