Jöcker
Jöcker

Reputation: 6798

How to set Anchor to Popover in Material-UI

I have a Popover in Material-UI from which I want to permanently set the anchor to a button. Not only on click with event.currentTarget. How can I do this with typescript?

Unfortunately, the current examples in Material-UI use event.currentTarget and with a reference it is not working.

import React,{useRef} from 'react';
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
import Popover from '@material-ui/core/Popover';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    typography: {
      padding: theme.spacing(2),
    },
  }),
);

export default function SimplePopover() {
  const classes = useStyles();

  const ref = useRef(null)


  return (
    <div>
      <Button ref={ref}  variant="contained" color="primary">
        Open Popover
      </Button>
      <Popover
        open
        anchorEl={ref}
        anchorOrigin={{
          vertical: 'bottom',
          horizontal: 'center',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'center',
        }}
      >
        <Typography className={classes.typography}>The content of the Popover.</Typography>
      </Popover>
    </div>
  );
}

Here a codesandbox for it.

Upvotes: 6

Views: 12034

Answers (2)

Akber Iqbal
Akber Iqbal

Reputation: 15041

2 things

  • you need to store the state of opened popup
  • open it from the outside
  • close it from the inside

relevant JS:

import React, { useRef, useState } from "react";
import { makeStyles, createStyles, Theme } from "@material-ui/core/styles";
import Popover from "@material-ui/core/Popover";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    typography: {
      padding: theme.spacing(2)
    }
  })
);

export default function SimplePopover() {
  const classes = useStyles();

  const ref = useRef(null);

  const [popOverVisible, setPopOverVisible] = useState(false);
  const togglePopOver = () => {
    popOverVisible === false
      ? setPopOverVisible(true)
      : setPopOverVisible(false);
  };

  return (
    <div>
      <Button
        ref={ref}
        variant="contained"
        color="primary"
        onClick={togglePopOver}
      >
        Open Popover
      </Button>
      Status: {popOverVisible.toString()}
      <Popover
        open={popOverVisible}
        anchorEl={ref}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "center"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "center"
        }}
      >
        <Button
          ref={ref}
          variant="contained"
          color="primary"
          onClick={togglePopOver}
        >
          CLOSE Popover
        </Button>
        <Typography className={classes.typography}>
          The content of the Popover.
        </Typography>
      </Popover>
    </div>
  );
}

EDIT: upon the user's comment below:

      <Popover
    open={popOverVisible}
    anchorEl={ref}
    anchorReference="anchorPosition"
    anchorPosition={{ top: 50, left: 140 }}
    anchorOrigin={{
      vertical: "bottom",
      horizontal: "left"
    }}
    transformOrigin={{
      vertical: "top",
      horizontal: "left"
    }}
  >

forked sandbox here

Upvotes: 4

hgb123
hgb123

Reputation: 14891

You must have missed some detail. I followed the Simple Popover example in official docs and it still works.

If you want to use useRef, make sure to refer to buttonRef.current when setting anchorRef

Below is the forked codesandbox:

Edit Popover Anchor

Upvotes: 9

Related Questions