James Brightman
James Brightman

Reputation: 935

How to dynamically position a IonPopover to appear from a button?

I'm trying to position a popover to appear underneath a button when that button is clicked. An example of this is on the Ion docs page. enter image description here

However the code for this is not supplied in React, only in Angular.

Currently my code looks like this

...
<IonButtons slot="end">
                        <IonButton onClick={() => setShowPopover(true)} expand="block">
                            <IonIcon icon={more}/>
                        </IonButton>
                    </IonButtons>
                    <IonPopover
                        isOpen={showPopover}
                        backdropDismiss={true}
                        onDidDismiss={() => setShowPopover(false)}>
                        <IonItem>Popover Item</IonItem>
                    </IonPopover>
...

The popover is toggled by the button above it. When the button is pressed the popover appears in the middle of the page, not over the button. How do I change this so the popover is shown attached to the button? (Like the image)

Thanks

Upvotes: 3

Views: 3308

Answers (2)

Yannic Hamann
Yannic Hamann

Reputation: 5205

Inspired by the answer of Thomas but unable to make his code work the following did the trick for me:

const [showPopover, setShowPopover] = useState<{open: boolean, event: Event | undefined}>({
  open: false,
  event: undefined,
});

<IonPopover
    isOpen={showPopover.open}
    event={showPopover.event}
    onDidDismiss={e => setShowPopover({open: false, event: undefined})}
>
   <p>This is popover content</p>
</IonPopover>
<IonButton onClick={(e) => setShowPopover({open: true, event: e.nativeEvent})}>Click</IonButton>

Upvotes: 13

Thomas
Thomas

Reputation: 8849

From the docs:

To present a popover, call the present method on a popover instance. In order to position the popover relative to the element clicked, a click event needs to be passed into the options of the the present method. If the event is not passed, the popover will be positioned in the center of the viewport.

So you need to pass the click event to the popover's event property.

I've never looked at React, but you might be able to add it to the state:

Updated example:

import React, { useState } from 'react';
import { IonPopover, IonButton } from '@ionic/react';

export const PopoverExample: React.FC = () => {
  const [showPopover, setShowPopover] = useState<{open: boolean, event: Event | null}>({
    open: false,
    event: null,
  });

  return (
    <>
      <IonPopover
        isOpen={showPopover.open}
        event={showPopover.event}
        onDidDismiss={e => setShowPopover({open: false, event: null})}
      >
        <p>This is popover content</p>
      </IonPopover>
      <IonButton onClick={(e) => setShowPopover({open: true, event: e})}>Show Popover</IonButton>
    </>
  );
};

Upvotes: 1

Related Questions