Reputation: 55
I'm trying to use multiple popovers on one page, but the only popover to open is the last one in the array, regardless of which trigger element you hover on. This is using Material-UI v1.0.0-beta.46.
class MultiplePopover extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
open: false,
anchorEl: null,
};
this.handlePopoverOpen = this.handlePopoverOpen.bind(this);
this.handlePopoverClose = this.handlePopoverClose.bind(this);
}
handlePopoverOpen(event) {
this.setState({
anchorEl: event.target,
});
}
handlePopoverClose() {
this.setState({
anchorEl: null,
});
}
render() {
const { classes } = this.props;
const { anchorEl } = this.state;
const open = !!anchorEl;
const multi = [
{
_id: 0,
name: 'name1',
hoverText: 'text1',
linkUrl: '#',
},
{
_id: 1,
name: 'name2',
hoverText: 'text2',
linkUrl: '#',
},
{
_id: 2,
name: 'name3',
hoverText: 'text3',
linkUrl: '#',
},
]
return (
<div className="wrapper">
<ul>
{multi.map(m => (
<li
key={m._id}
>
<Typography
onMouseEnter={this.handlePopoverOpen}
onMouseLeave={this.handlePopoverClose}
>
{m.name}
</Typography>
<Popover
className={classes.popover}
classes={{
paper: classes.paper,
}}
open={open}
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
>
<Typography>
<a
href="{m.linkUrl}"
target=" /blank"
>
{m.hoverText}
</a>
</Typography>
</Popover>
</li>
))}
</ul>
</div>
);
}
}
I have tried to follow the answer from this post Popover doesn't work if you have many of them on one page. How to manage them? but I couldn't get it working.
Any idea how I could get each popover to open separately?
You can see a live example here: https://codesandbox.io/s/1r1zjmj163
Upvotes: 4
Views: 10914
Reputation: 41
@asiniy Why does commenting out the css 'pointerEvents' cause the popovers code to break? If there are links inside the popover this will cause problems. Should css control the events??
popover: {
//pointerEvents: 'none',
},
Upvotes: 1
Reputation: 15216
You're doing it a little bit wrong.
First. open
declares that only some element exists in state but it doesn't declares which one is opened. I've brought new openedPopoverId
to the state (null by default). So, in this case, you have to check in your Popover
component
open={this.state.openedPopoverId === m._id}
Second. You have to pass this value on mouseEnter event, so that:
<Typography
onMouseEnter={this.handlePopoverOpen}
becomes
onMouseEnter={(e) => this.handlePopoverOpen(e, m._id)}
Third. Change event handlers as well:
handlePopoverOpen(event, popoverId) {
this.setState({
openedPopoverId: popoverId,
anchorEl: event.target,
});
}
handlePopoverClose() {
this.setState({
openedPopoverId: null,
anchorEl: null,
});
}
Final code (tested, it works):
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Typography from 'material-ui/Typography';
import Popover from 'material-ui/Popover';
const styles = ({
paper: {
padding: '20px',
width: '14vw',
},
popover: {
pointerEvents: 'none',
},
});
class MultiplePopover extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
open: false,
anchorEl: null,
};
this.handlePopoverOpen = this.handlePopoverOpen.bind(this);
this.handlePopoverClose = this.handlePopoverClose.bind(this);
}
handlePopoverOpen(event, popoverId) {
this.setState({
openedPopoverId: popoverId,
anchorEl: event.target,
});
}
handlePopoverClose() {
this.setState({
openedPopoverId: null,
anchorEl: null,
});
}
render() {
const { classes } = this.props;
const { anchorEl, openedPopoverId } = this.state;
const multi = [
{
_id: 0,
name: 'name1',
hoverText: 'text1',
linkUrl: '#',
},
{
_id: 1,
name: 'name2',
hoverText: 'text2',
linkUrl: '#',
},
{
_id: 2,
name: 'name3',
hoverText: 'text3',
linkUrl: '#',
},
]
console.log(openedPopoverId)
return (
<div className="wrapper">
<ul>
{multi.map(m => (
<li
key={m._id}
>
<Typography
onMouseEnter={(e) => this.handlePopoverOpen(e, m._id)}
onMouseLeave={this.handlePopoverClose}
>
{m.name}
</Typography>
<Popover
className={classes.popover}
classes={{
paper: classes.paper,
}}
open={openedPopoverId === m._id}
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
>
<Typography>
<a
href="{m.linkUrl}"
target=" /blank"
>
{m.hoverText}
</a>
</Typography>
</Popover>
</li>
))}
</ul>
</div>
);
}
}
MultiplePopover.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(MultiplePopover);
Upvotes: 14