Reputation: 61
I have an array of items I would like to create Panels out of which would eventually be inserted into the Accordion.
In one file, I have:
var items = this.state.contents.map(function(content, index) {
return <Content {...content}, key={index}/>
};
return (
<Accordion>
{items}
</Accordion>
);
In another file called Content I have:
return(
<Panel header={this.props.header} eventKey={this.props.key}>
{this.props.body}
</Panel>
);
When I have the Accordion and Panel in the same file, they work. But when I generate the Panel using map after splitting them into two files, it doesn't seem to collapse.
Upvotes: 3
Views: 5435
Reputation: 1
The easiest way to do it is making a condition inside the eventKey parameter.
<Card key={item.id}>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey={index === 0 ? '0' : index}>
{item.title}
</Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey={index === 0 ? '0' : index}>
<Card.Body>
CARD BODY
</Card.Body>
</Accordion.Collapse>
</Card>
Upvotes: 0
Reputation: 21
For anyone using Accordion.Toggle, this is how I got the accordion to collapse on map.
In the parent component of the Accordion, add an activeKey value to the state. Create a function to handle the active key change that will be passed down during your map to each child component of the accordion. Be sure to bind that function to the parent component.
this.state = {
items = []
activeKey: ''
}
handleActiveKeyChange = activeKey => {
if (this.state.activeKey === activeKey) {
//allows us to close expanded item by clicking its toggle while open
activeKey = -1
}
this.setState({ activeKey })
}
Pass the active key state and function accordingly in your render method:
<Accordion activeKey={this.state.activeKey}>
{this.state.items.map((item, index) => (
<Item eventKey={index} handleActiveKeyChange={this.handleActiveKeyChange} />
))}
</Accordion
In your child (item) element's Accordion toggle, add the passed function and props:
<Card>
<Card.Header>
<Accordion.Toggle
eventKey={this.props.eventKey}
onClick={() => this.props.handleActiveKeyChange(this.props.eventKey)}
>
//+ icon here
</Accordion.Toggle>
</Card.Header>
//card content here
</Card
Upvotes: 2
Reputation: 66
Here is the solution
<Accordion>
{this.item.map(item =>
<AcPanel key={item.id} item={item} eventKey={item.id} />
)}
</Accordion>
In AcPanel Class use {...this.props} for fetch all properties and assign values on your parent class like i used "eventKey={item.id}".
<Panel header={`Collapsible Group Item`} bsClass='class-name' {...this.props}>
content here
</Panel>
Upvotes: 2
Reputation: 2957
I found a solution that lets you use a component in a separate file.
I figured the problem must be to do with the Accordion
not being able to pass some props down to the Panel
because they go to the wrapping component instead, so I tried collecting all the props that weren't mine and passing them to the panel:
// make sure you have all your own props specified before ...props
// so that they can't mess up the panel.
const { body, ...props } = this.props
return(
<Panel {...props}>
{body}
</Panel>
);
If you want to specify any props on the Panel
, make sure they go after the collected props so that they take precedence over any defaults:
const { body, ...props } = this.props
return(
<Panel {...props}
bsStyle="info">
{body}
</Panel>
);
If you choose any props names the same as whatever Accordion
is passing to Panel
, you could clobber something and break it - if you're concerned, it should be straightforward to follow the code and see what is being passed on.
Upvotes: 1
Reputation: 61
react-bootstrap seems to complain if the children of an Accordion are not Panels, and by wrapping Panel inside of my Content class I was doing just that.
To solve this problem I had to step away from React's convention. Rather than creating a class Content, I created another js file rather than a react.js file. By treating this file like a normal js file, I was able to call on a function inside of this file which maps over each 'this.state.contents' and return a Panel object.
This whole file will return an array of Panel class.
Upvotes: 0