Reputation:
I am using Material UI accordion my issue is if I click on the arrow accordion will get open but again I click on the arrow it will not get closed I need to set it when the user clicks on the arrow according will close and open based on the arrow click check code sandbox link for better understanding.
export default function ControlledAccordions() {
const [expanded, setExpanded] = React.useState(false);
// const handleChange = (panel) => (event, isExpanded) => {
// setExpanded(isExpanded ? panel : false);
// };
const handleChange = (pannel) => {
setExpanded(pannel);
};
const panaalData = ["panel1", "panel2", "panel3", "panel4"];
return (
<div>
{panaalData.map((value, i) => {
return (
<Accordion expanded={expanded === `panel${i}`}>
<AccordionSummary
expandIcon={
<ExpandMoreIcon
onClick={() => {
handleChange(`panel${i}`);
}}
style={{ cursor: "pointer" }}
/>
}
aria-controls="panel1d-content"
id="panel1d-header"
>
fdsfdsf
</AccordionSummary>
<AccordionDetails>dfdf</AccordionDetails>
</Accordion>
);
})}
</div>
);
}
Upvotes: 1
Views: 1007
Reputation: 49293
export default function ControlledAccordions() {
// initial state, everything is closed,
const [expandedIndex, setExpandedIndex] = React.useState(-1);
// this should be handleClic
const handleChange = (index) => {
// in useState, current expandedIndex is passed as the argument
// whatever we return will be set as the expandedIndex
setExpandedIndex((currentIndex) => {
// if any box is open, currentIndex will be that index
// when I click on the open box, it will set the expandedIndex=-1
if (currentIndex === index) {
return -1;
} else {
// If I reached here, that means I am on a closed box
// when I click I swithc the expandedIndex to current box's index
return index;
}
});
};
const panaalData = ["panel1", "panel2", "panel3", "panel4"];
return (
<div>
{panaalData.map((value, i) => {
// when handleChange runs on AccordionSummary expandedIndex===i
// that means when i click on the current box, it will be open
const isExpanded = expandedIndex === i;
return (
<Accordion expanded={isExpanded}>
<AccordionSummary
onClick={() => handleChange(i)}
expandIcon={
// I dont know @mui/material too much.
// main question is "I need to open and close accordion based on arrow click"
<ExpandMoreIcon
onClick={() => handleChange(i)}
style={{ cursor: "pointer" }}
/>
}
aria-controls="panel1d-content"
id="panel1d-header"
>
{value}
</AccordionSummary>
<AccordionDetails
style={{ backgroundColor: "green" }}
>{`box index ${i} is open`}</AccordionDetails>
</Accordion>
);
})}
</div>
);
}
proof of work:
Upvotes: 0
Reputation: 13245
Create another component called MyAccordian
and keep toggling accordion logic in that component. That way you don't need to handle toggling for each and every component separately.
export default function ControlledAccordions() {
const panaalData = ["panel1", "panel2", "panel3", "panel4"];
return (
<div>
{panaalData.map((value, i) => {
return <MyAccordian value={value} />;
})}
</div>
);
}
const MyAccordian = ({ value }) => {
const [expanded, setExpanded] = React.useState(false);
return (
<Accordion expanded={expanded}>
<AccordionSummary
expandIcon={
<ExpandMoreIcon
onClick={() => {
setExpanded((prev) => !prev);
}}
style={{ cursor: "pointer" }}
/>
}
aria-controls="panel1d-content"
id="panel1d-header"
>
{value}
</AccordionSummary>
<AccordionDetails>{value}</AccordionDetails>
</Accordion>
);
};
Working Demo
Upvotes: 0
Reputation: 464
when you click the already expanded panel, it just sets it to be expanded again.
you need to check whether the clicked panel is already expanded and if so collapse it instead of expanding it:
const handleChange = (pannel) => {
if (expanded === pannel) setExpanded(false);
else setExpanded(pannel);
};
Upvotes: 1
Reputation: 672
you need to reset panel in that case. You can do that in change handler.
const handleChange = (pannel) => {
setExpanded(expended === pannel ? '' : pannel);
};
Upvotes: 1