How to programmatically expand a specific pannel in Ant design collapse - reactjs

I want to expand a specific pannel of the Ant design collapse by clicking the next button it should expand the next panel. Here is the codesandbox link. Here is the screenshot of it as well.

You just need to save the key in state of panel that you want to open it. You want to open the second panel when button in first panel is clicked. You save that Panel key is state and need to pass that active key to Collapse as a prop.
const App: React.FC = () => {
const [activeKey, setActiveKey] = useState(1);
function handleClick(key) {
setActiveKey(key);
}
return (
<Collapse defaultActiveKey={["1"]} activeKey={activeKey} ghost>
<Panel header='This is panel header 1' key='1'>
<p>{text}</p>
<button onClick={() => handleClick("2")}>Next</button>
</Panel>
<Panel header='This is panel header 2' key='2'>
<p>{text}</p>
<button onClick={() => handleClick("3")}>Next</button>
</Panel>
<Panel header='This is panel header 3' key='3'>
<p>{text}</p>
</Panel>
</Collapse>
);
};
export default App;
Since you didn't provide specify whether it should close the existing panel or not. It does close the existing panel then above solution fines. But if you want to open multiple panels at a time then you need to change the code.
<Collapse activeKey={activeKey}>
You can activeKey as an array instead of string or number. In array you can pass any number of Panel keys like this: ['1', '2', ...].
Check the Antd Collapse API

I found a solution finally
const App: React.FC = () => {
const [activeKey, setActiveKey] = useState(['1']);
function handleClick(key) {
console.log(key)
setActiveKey(key);
}
return (
<Collapse
defaultActiveKey={["1"]}
activeKey={activeKey}
ghost
onChange={handleClick}
>
<Panel header="This is panel header 1" key="1">
<p>{text}</p>
<button value='2' onClick={(e) => handleClick(e.target.value)}>Next</button>
</Panel>
<Panel header="This is panel header 2" key="2">
<p>{text}</p>
<button value='3' onClick={(e) => handleClick(e.target.value)}>Next</button>
</Panel>
<Panel header="This is panel header 3" key="3">
<p>{text}</p>
</Panel>
</Collapse>
);
};
export default App;
Here is the codesandbox link

Related

Ant design Collapse - expand / collapse all button

How can I have a button triggering an ant.design Collapse component to expand all its tabs, or collapse all of them? I tried changing defaultActiveKey but I get the impression that this can only be changed when the page is rendered? If not, could someone provide a short snippet of a button collapsing multiple panels? The number of panels I have is set.
You should use component in controlled mode, that is you should supply value of panels which are open. For that you should use activeKey prop. Here is example:
let App = () => {
let [openPanels, setOpenPanels] = React.useState([]);
return (
<Collapse activeKey={openPanels} onChange={setOpenPanels}>
<Panel header="This is panel header 1" key="1">
<p>test1</p>
</Panel>
<Panel header="This is panel header 2" key="2">
<p>test2</p>
</Panel>
<Panel header="This is panel header 3" key="3">
<p>test3</p>
</Panel>
</Collapse>
);
};
Now you can easily add a button and on click set setOpenPanels([]) to collapse all of them.

Trigger AntDesign (React) sider using custom button without this.state

I'm using AntD Sider ... but I don't want to use the sider button which makes it pop out. I'm currently writing this entire thing in a function so I can't use this.state as specified in the antd docs examples.
const [collapsed, setcollapsed] = useState(false);
return (
<>
<Sider collapsible collapsed={collapsed} onCollapse={setcollapsed} collapsedWidth={0} reverseArrow>
<Menu>
<Menu.Item></Menu.Item>
<Menu.Item></Menu.Item>
<Menu.Item></Menu.Item>
</Menu
</Sider
<Button shape="circle" style={styles.button} onClick={collapsed}>
<MenuOutlined />
</Button>
Is there a way to make this button trigger the sider? ^
unlike this ^[*]
<Sider collapsible collapsed={collapsed} onCollapse={setcollapsed} collapsedWidth={0} reverseArrow></Sider>
Code for [*]
Try this onClick handler please:
<Button shape="circle" style={styles.button} onClick={() => setcollapsed((prev) => !prev)}>
<MenuOutlined />
</Button>
And remove onCollapse from here
<Sider collapsible collapsed={collapsed} collapsedWidth={0} reverseArrow>
<Menu>
<Menu.Item></Menu.Item>
<Menu.Item></Menu.Item>
<Menu.Item></Menu.Item>
</Menu
</Sider

how to expand only one collapse panel in ant-design

I'm using Ant-design collapse as accordian , my requirement is when I load page by default first panel should open, and also when I click on other panel whartever the panel is already open should close and only clicked panel should expand.Can someone please help me on this.
I'm using Ant-design collapse :
https://ant.design/components/collapse/
Regards,
You need to use 'accordion' and 'defaultActiveKey' properties. Something like:
import { Collapse } from 'antd';
const { Panel } = Collapse;
const text = `
A dog is a type of domesticated animal.
Known for its loyalty and faithfulness,
it can be found as a welcome guest in many households across the world.
`;
ReactDOM.render(
<Collapse accordion defaultActiveKey={['1']}>
<Panel header="This is panel header 1" key="1">
<p>{text}</p>
</Panel>
<Panel header="This is panel header 2" key="2">
<p>{text}</p>
</Panel>
<Panel header="This is panel header 3" key="3">
<p>{text}</p>
</Panel>
</Collapse>,
mountNode,
);

How to make the Collapse position to bottom-right after clicking on expand icon in AntD

I am using AntD Collapse for displaying a list of items after expand icon is clicked.
I want the position of expandIcon to go to bottom-right after all the list of the data when expand icon is clicked (just like in google news), but found only two options (left|right) for 'expandIconPosition', no option for top or bottom.
How can we align the expandIcon to bottom-right, when expand icon is clicked?
Few lines from the code for reference:
<Collapse
ghost
style={{ marginTop: "-1vh" }}
expandIcon={({ isActive }) => (
<DownOutlined
style={{ marginTop: "-2vh" }}
rotate={isActive ? 180 : 0}
/>
)}
expandIconPosition="right"
>
<Panel>
<div>
{list()} //list of items
</div>
</Panel>
</Collapse>
Here's one possible solution. Make Collapse a controlled component by specifying activeKey prop and then the value of it will be based on state. Then, by tracking the activeKeys state you can now do a conditional rendering (hide and show) on icons:
const [activePanelKeys, setActivePanelKeys] = useState([]);
const handlePanelIconClick = (panelKey, makeActive) => {
if (makeActive) {
setActivePanelKeys([...activePanelKeys, panelKey]);
} else {
setActivePanelKeys(activePanelKeys.filter((aPK) => aPK !== panelKey));
}
};
<Collapse
activeKey={activePanelKeys}
expandIconPosition="right"
expandIcon={() => <DownOutlined />}
// expandIcon={(panelProps) => (
// <DownOutlined
// onClick={() => handlePanelIconClick(panelProps.panelKey, true)}
// />
// )}
onChange={e => setActivePanelKeys(e)} //if you want to click only icon, comment this and uncomment the above expandedIcon
>
<Panel
header="This is panel header 1"
key="p1"
showArrow={activePanelKeys.indexOf("p1") === -1}
>
<div>{text}</div>
{activePanelKeys.indexOf("p1") !== -1 && (
<div style={{ textAlign: "right", marginTop: 10 }}>
<UpOutlined onClick={() => handlePanelIconClick("p1", false)} />
</div>
)}
</Panel>
{/* <PanelContent header="This is panel header 2" key="p2">
{text}
</PanelContent> */}
</Collapse>;
Here is the complete sample code:
Note: I tried to make a reusable Panel component but it seems that the reveal animation were gone. You can uncomment the commented PanelContent on the code to see the difference.
Hope that I hit what you want.

how do i open only one panel when I use mapping in react for panels

I have created a panel to map through my users and display their songs below their name.
The problem im having is that when I click on the {username} it opens all of the accordion panels. I'd like it to only open the accordion for the panel being clicked.
<PanelGroup accordion id="accordion-example">
{this.state.allUsersList.map((user, index) => (
<Panel>
<Panel.Heading>
<Panel.Title toggle >
<Button key={index} className="btn-uvideo">{user.Username}</Button>
</Panel.Title>
</Panel.Heading>
<Panel.Body collapsible>
<ListGroup>
{user.songs.map((song, index) => (
<ListGroupItem key={index}>
<Button className="btn-video" onClick={() => this.handleSongChange(song)}>
<p>{song.SongName}</p>
</Button>
</ListGroupItem>
))}
</ListGroup>
</Panel.Body>
</Panel>
))}
</PanelGroup>
I'm assuming you're using React-Bootstrap. Looks like you're missing eventKey:
A unique identifier for the Component, the eventKey makes it distinguishable from others in a set. Similar to React's key prop, in that it only needs to be unique amoungst the Components siblings, not globally.
https://react-bootstrap.github.io/components/panel/#panels-accordion
<PanelGroup accordion id="accordion-example">
<Panel eventKey="1">
...
</Panel>
<Panel eventKey="2">
...
</Panel>
<Panel eventKey="3">
...
</Panel>
</PanelGroup>
Assuming your usernames are unique you can use that value for your eventKey:
<PanelGroup accordion id="accordion-example">
{this.state.allUsersList.map((user, index) => (
<Panel eventKey={user.Username}>
...

Resources