Ionic android modal not over perviours modal on top view năm 2024

I'm going to share this because it took me a couple hours of research and experimenting to achieve something that in my opinion should be the default behavior.

The issue :

So let's say you want to use a modal to display some information in your Ionic PWA (In my case I was displaying a list of articles, and I wanted to display the full article in a modal so as to not completely change page). You probably have a "back" or "cancel" button somewhere in your modal, and if your screen is big enough to see the rest of the page behind you can click that to dismiss the modal. So far so good !

Now the problem is that many users will want to use the hardware back button on their mouse or their phone to dismiss the modal (especially on a small screen where the modal takes the whole screen and looks like a new page), and in that case the default behavior is that it will change the actual page that's still behind your modal to the previous page... Which is definitely not what you would expect to happen.

The solution :

From Angular's perspective it makes sense : As far as the router component is concerned you never changed page (you just put a huge popup in front of your page), and hitting back will just bring you to the previous page... So let's change that !

1. Dismiss the Pop-up when the back button is pressed

This can be done easily with the @HostListener() decorator, which allows you to listen for a DOM event and trigger the decorated method when it happens. So in our modal component we can listen for the history popState and dismiss our modal :

  @HostListener('window:popstate', ['$event'])
  dismissModal() {
    this.modalController.dismiss();
  }

Enter fullscreen mode Exit fullscreen mode

Chances are you already have a method that dismisses your modal that you may call from a "cancel" or "close" button in your html. If that's the case you don't need to create a new method, you can just add the decorator to your existing method.

That should work great for dismissing the modal, except won't prevent the back button from also going back in the history and switch to the previous page.

2. Don't go back to the previous page after dismissing the modal

Unfortunately there doesn't seem to be a way to prevent the default behavior of the back button, so we'll need to be get clever. One solution is to push a "fake" state for our modal in the history when it's displayed, that way the popState event will just get rid of that fake state. We can put anything we want in the "state" parameter of history.pushState(), so we'll put a modal boolean in case we later need to check if a specific state was created for a modal. Let's so it in our ngOnInit method :

  ngOnInit() {
      const modalState = {
          modal : true,
          desc : 'fake state for our modal'
      };
      history.pushState(modalState, null);
  }

Enter fullscreen mode Exit fullscreen mode

This is good. But there's still a tiny little problem : What happens if the user dismisses the modal without using the back button (by clicking on the close button in the modal itself, or clicking outside of the modal) ? We're left with a phantom state in our history and the next time they press back nothing will happen !

3. Remove any phantom history when the modal is dismissed

We'll need to manually cleanup the history in this case. So let's use our modal to remove the last state if needed when we dismiss our modal in the ngDestroy() method :

  ngOnDestroy() {
    if (window.history.state.modal) {
      history.back();
    }
  }

Enter fullscreen mode Exit fullscreen mode

And NOW we're good to go. We should have covered all cases and it will give the perfect illusion that you can dismiss a popup with the back button !

Here's the whole component with the constructor and our 3 methods :

import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
import { ModalController } from '@ionic/angular';
@Component({
  selector: 'app-mymodal',
  templateUrl: './mymodal.page.html',
  styleUrls: ['./mymodal.page.scss'],
})
export class MyModalComponent implements OnInit, OnDestroy {
  constructor(
    private modalController: ModalController) {
  }
  ngOnInit() {
    const modalState = {
      modal : true,
      desc : 'fake state for our modal'
    };
    history.pushState(modalState, null);
  }
  ngOnDestroy() {
    if (window.history.state.modal) {
      history.back();
    }
  }
  @HostListener('window:popstate', ['$event'])
  dismissModal() {
    this.modalController.dismiss();
  }
}

Enter fullscreen mode Exit fullscreen mode

Thanks for reading ! So far it seems to work fine for me but let me know if I missed anything or if you have another solution.

How to pass data to ionic modal?

Pass Data to your Modal with Background Update By doing this, we can subscribe() to the changes on our page and later emit new values within the modal! I've used this pattern inside my new eBook Built with Ionic – check it out if you want to build even more epic interfaces with Animations and Gestures!

How do you show modal in ionic?

Using isOpen ​ The isOpen property on ion-modal allows developers to control the presentation state of the modal from their application state. This means when isOpen is set to true the modal will be presented and when isOpen is set to false the modal will be dismissed.

How to close modal ionic?

Developers can set canDismiss to a boolean value. If canDismiss is true , then the modal will close when users attempt to dismiss the modal. If canDismiss is false , then the modal will not close when users attempt to dismiss the modal.

How to open a pop

Inline popovers can also be opened by setting the isOpen property to true . This method can be used if you need finer grained control over the popover than with a trigger. isOpen uses a one-way data binding, meaning it will not automatically be set to false when the popover is dismissed.