Popover triggers backdrop dismiss when using press event

#1

Hey everyone,

I have an ion-list, where each item has a press event which triggers a popover.
On Android this works fine, but on iOS there’s something causing the popover to instantly dismiss as it shows. This happens about 80-90% of press events. Sometimes it doesn’t immediately dismiss.

On an actual device, you can press, and then while still pressing, you can slide your finger over the popover, which then seems to keep it open.

I need to have the popover stay open until you either tap outside of the popover or on one of the ion-items inside the popover.

If I set enableBackdropDismiss to false, then it stays open as expected.
So I guess there’s an additional tap event on the backdrop being triggered when it shouldn’t be.

This is the code for the home.ts page. Very straightforward, just loading up the popOver.

pressEvent(event: any) {
    console.log('Pressed...');
    this.presentPopover(event);
  }

  tapEvent() {
    console.log('Tapped...');
  }

  presentPopover(event: any) {
    let popover = this.popoverCtrl.create(MyPopOverPage, {}, { enableBackdropDismiss: false });
    popover.present({
      ev: event
    });
    this.popoverOpen = true;

    popover.onDidDismiss((popoverData) => {
      this.popoverOpen = false;
      console.log('Popover dismissed');
    });
  }

The list on the home.html is as follows.

<ion-list>
    <ion-item>
      <ion-avatar item-start (press)="pressEvent($event)" (tap)="tapEvent()">
        <img src="assets/imgs/avatar-ts-woody.png">
      </ion-avatar>
      <h2>Cher</h2>
      <p>Ugh. As if.</p>
    </ion-item>
  </ion-list>

Here’s what it looks like in the browser:

Any ideas on how to prevent the backdrop tap being incorrectly triggered? Or perhaps manually re-enable backdrop dismiss after the popover opens up?

Any help would be hugely appreciated!

Ionic info:

ionic info                                                           (master✱)                                                                                   (master✱)

cli packages: (/usr/local/lib/node_modules)

    @ionic/cli-utils  : 1.19.0
    ionic (Ionic CLI) : 3.19.0

global packages:

    cordova (Cordova CLI) : 7.1.0

local packages:

    @ionic/app-scripts : 3.1.6
    Cordova Platforms  : ios 4.5.4
    Ionic Framework    : ionic-angular 3.9.2

System:

    ios-deploy : 1.9.2
    ios-sim    : 5.0.4
    Node       : v6.11.2
    npm        : 3.10.10
    OS         : macOS High Sierra
    Xcode      : Xcode 9.2 Build version 9C40b

Environment Variables:

    ANDROID_HOME : not set

Misc:

    backend : pro
1 Like
#2

Same issue. I’ve tried timeouts, changing it’s size and nothing works

#3

I think I know why this is happening.
On iOS, the popover content is shown below the element that triggered the event.
What I think is happening is that as you trigger the press event, the backdrop appears under your finger, which seems to trigger a tap/click on the backdrop, causing it to dismiss.

If you ‘press’ just long enough to trigger a press instead of tap and then lift your finger it works fine, but keep touching the screen long enough for the popover to appear and you’ll trigger the backdrop dismiss when you lift your finger.

If I set enableBackDropDismiss to false, then it works, but this isnt a solution because then the user experience just isnt very intuitive.

This isnt an issue on Android because the popover appears under your finger / directly over the element you pressed, so you’re not tapping the backdrop.

Any ideas to either prevent that first backdrop tap (or within a certain delay) or to enable backdrop dismiss after a certain delay?

#4

I too am having this exact issue. I’ve thrown in enableBackDropDismiss=false to alleviate the issue, though if a user presses in the center of the screen, whichever button happens to be under their finger when the popover triggers is pressed as they lift off.

It seems this would have to be solved by manipulating the $event object or by triggering when the popover after the user is finished pressing (when their finger lifts off) instead of when the press gesture is first detected. But I can’t find how to do either in the docs

#5

I never did solve this, but looking at it again now, I’m thinking this would need to be a change in the Ionic Popover code as nothing in the usage or options would seem to provide for this situation.

In the Popover component, line 61-65:

    PopoverCmp.prototype._bdClick = function () {
        if (this._enabled && this.d.enableBackdropDismiss) {
            return this._viewCtrl.dismiss(null, 'backdrop');
        }
    };

My guess is the best option would for the _bdClick() function to somehow check if the gesture is a ‘finger lift off’ after a long press. The function isn’t taking any args though, so any suggestion on how to check the firing event?

#6

I solved the issue this way:

let popover = this.popoverCtrl.create(PopoverMenu, {}, {
    enableBackdropDismiss: false
})

popover.present({
    ev: ev
}).then(() => {
    setTimeout(() => {
        let backgrounds = document.getElementsByTagName('ion-backdrop')

        if (backgrounds.length === 1) {
            backgrounds[0].addEventListener('click', function () {
                popover.dismiss()
            });
        }
    }, 300)
})

Essentially you disable the default backdrop dismiss in the popover config, then after the popover is displayed wait a short period and then attach a custom click handler to the backdrop which dismisses the popover manually.

2 Likes
#7

It worked for us, but I used 600 on timeout, instead of 300.
Thank you very much!

1 Like