Reputation: 9455
Well typically when we use popover we set the anchor during a mouse event to event.currentTarget
.
However this is impossible in certain situations and undesired in others. - How can I set the popover anchor element directly?
import React from "react";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
export default function SimplePopover() {
const [anchorEl, setAnchorEl] = React.useState(null);
function handleClick(event) {
//setAnchorEl(event.currentTarget);
setAnchorEl(); //How to refer to the div?
}
function handleClose() {
setAnchorEl(null);
}
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
return (
<div>
<Typography>Anchor point of popover here</Typography>
<Button aria-describedby={id} variant="contained" onClick={handleClick}>
Open Popover
</Button>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "center"
}}
transformOrigin={{
vertical: "top",
horizontal: "center"
}}
>
<Typography>The content of the Popover.</Typography>
</Popover>
</div>
);
}
Upvotes: 24
Views: 42472
Reputation: 81146
You can use a ref to get at whichever element you want to use as the anchor. The example below uses spanRef
to get at the element rendered by the Typography
element.
The placement of the Popover
relative to the anchor element is then dependent on the anchorOrigin
and transformOrigin
properties. In the example below, the top-left corner of the Popover
will be aligned with the bottom-right corner of the span. I changed the component of the Typography
from the default <p>
element to <span>
to make the positioning easier to see. Since block elements (such as <p>
) have 100% width by default even if the contents don't take up much of that space, the Popover
can appear to be far away from the anchor if the anchor element is much wider than is visually apparent.
import React from "react";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
export default function SimplePopover() {
const [anchorEl, setAnchorEl] = React.useState(null);
const spanRef = React.useRef();
function handleClick() {
setAnchorEl(spanRef.current);
}
function handleClose() {
setAnchorEl(null);
}
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
return (
<div>
<Typography component="span" ref={spanRef}>
Anchor point of popover here
</Typography>
<br />
<Button aria-describedby={id} variant="contained" onClick={handleClick}>
Open Popover
</Button>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
}}
transformOrigin={{
vertical: "top",
horizontal: "left"
}}
>
<Typography>The content of the Popover.</Typography>
</Popover>
</div>
);
}
Upvotes: 32
Reputation: 648
This is a small variation from Ryan Cogswell example to open automatically the Popover:
https://codesandbox.io/s/use-ref-for-anchorel-forked-ou7eo
import React, { useEffect } from "react";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
export default function SimplePopover() {
const [anchorEl, setAnchorEl] = React.useState(null);
const divRef = React.useRef();
function handleClick() {
setAnchorEl(divRef.current);
}
function handleClose() {
setAnchorEl(null);
}
useEffect(() => {
setAnchorEl(divRef.current);
}, [divRef]);
const open = Boolean(anchorEl);
const id = open ? "simple-popover" : undefined;
return (
<div>
<Typography>Anchor point of popover here</Typography>
<Button
ref={divRef}
aria-describedby={id}
variant="contained"
onClick={handleClick}
>
Open Popover
</Button>
<Popover
id={id}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "center"
}}
transformOrigin={{
vertical: "top",
horizontal: "center"
}}
>
<Typography>The content of the Popover.</Typography>
</Popover>
</div>
);
}
Upvotes: 1