Markus
Markus

Reputation: 1292

Close Modal in Ionic 4 by Back Button

I have a Modal in Ionic 4. I'd like to close it, when a user press the back button on her mobile (or the back button in her browser).

Does anyone know how I can do this?

EDIT: More details:

I have a button that opens my modal:

async onClick() {
  const modal = await this.modalController.create({
    component: Foo,
  });
  return await modal.present();
}

Component Foo doesn't have much more content than a button that closes the modal: this.modalController.dismiss();. So far so good.

On my mobile, however, the app now closes when the modal is open and the user taps the mobile's back button. But in this case only the modal should close.

Upvotes: 13

Views: 32628

Answers (7)

Bryan Lim
Bryan Lim

Reputation: 601

You can also use the built in function of ionic which is

   <ion-back-button>
   </ion-back-button> 

You can also position the <ion-back-button> to start or end

<ion-buttons slot="start">
   <ion-back-button>
   </ion-back-button>
</ion-buttons>

for more information about <ion-back-button> Here's a link

Upvotes: 0

Grant
Grant

Reputation: 6309

Update, for Ionic 5 (Angular)

in your-modal.page.ts

import { ModalController } from '@ionic/angular';

at the top of your modal's .ts file. Then in your constructor you can just denote a -public- relationship to the controller, that way it's accessible by your view.

also in your-modal.page.ts

constructor(
    public modalCtrl: ModalController
) {}

Now you can inline the close command:

in your-modal.page.html

<ion-header color="dark">
  <ion-toolbar color="dark">
    <ion-title>Modal Title</ion-title>
    <ion-buttons slot="primary">
      <ion-button (click)="modalCtrl.dismiss()">
        <ion-icon slot="icon-only" name="close"></ion-icon>
      </ion-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

Slot "primary" makes the buttons move to the right in iOS.

Upvotes: 0

Njehuu
Njehuu

Reputation: 69

For ionic 5 user

this.platform.backButton.subscribeWithPriority(999, async() => {
    if (this.modalCtrl.getTop()) {
        const modal = await this.modalCtrl.getTop();
        console.log(modal)
        if (modal) { 
            this.modalCtrl.dismiss();
            return;
        } else {
            if (this.router.url=="/myrootpage" ) {
            navigator['app'].exitApp();
        } else {
            this.navCtrl.pop();
        }
    }
    } else {
        if (this.router.url=="/myrootpage") {
            navigator['app'].exitApp();
        } else {
            this.navCtrl.pop();
        }
    } 
});

Upvotes: 4

Yes, are almost on the way.... you just need to change in HTML part. I did in this way.

<ion-header>
    <ion-toolbar>
        <ion-buttons slot="start">
            <ion-button color="dark" (click)="closeModal()">
                <ion-icon name="arrow-back"></ion-icon>
            </ion-button>
        </ion-buttons>
        <ion-title>Create Pin</ion-title> 
    </ion-toolbar>
</ion-header>

after this, you just need to create a function that will close your modal popup. in your ts file

closeModal() {
    this.modalCtrl.dismiss();
}

I hope that will help you.

Upvotes: 1

zimejin
zimejin

Reputation: 1

Based on the initial answer by Markus, You can decide to; Instead of unsubscribing after each back button event. You may want to listen to back-button events globally in your application and only call exit on specific pages.

import { fromEvent } from "rxjs";           // import fromEvent from rxjs
import { Router } from "@angular/router";   // import angular router as well
import { Location } from "@angular/common"; // import location from angular common
    
constructor(private router: Router, private location: Location) {

// Call the function when the app initializes at app.component.ts. it will watch for // back button events globally in the application.

  this.backButtonEvent();
}

// Function to present the exit alert
   async exitAlert() {
    const alert = await this.alertController.create({
      // header: 'Confirm!',
      message: "Are you sure you want to exit the app?",
      buttons: [
        {
          text: "Cancel",
          role: "cancel",
          cssClass: "secondary",
          handler: blah => {}
        },
        {
          text: "Close App",
          handler: () => {
            navigator["app"].exitApp();
          }
        }
      ]
    });

    await alert.present();
  }
    
      // function to subscribe to the backbutton event
      backButtonEvent(): void {
        const event = fromEvent(document, "backbutton");
        event.subscribe(async () => {
        // When the current route matches a specific page/route in the app where u 
        // want to exit on back button press.
    
        // else assume the user wants to navigate to a previous page
         if(this.router.url === "<example page-url to exit from>") { this.exitAlert() 
        }
         else { this.location.back() } 
        });
      } 

Upvotes: 0

Markus
Markus

Reputation: 1292

Enol's answer helped me find a solution, thanks for that.

platform.registerBackButtonAction does no longer exist in v4. I tried platform.backButton.subscribe instead, but it didn't work. What works is this:

private backbuttonSubscription: Subscription;

constructor(private modalCtrl: ModalController) {

ngOnInit() {
    const event = fromEvent(document, 'backbutton');
    this.backbuttonSubscription = event.subscribe(async () => {
        const modal = await this.modalCtrl.getTop();
        if (modal) {
            modal.dismiss();
        }
    });
}

ngOnDestroy() {
    this.backbuttonSubscription.unsubscribe();
}

Upvotes: 18

You can use the registerBackButtonAction method that Platform service contains. This method allows override the default native action of the hardware back button. The method accepts a callback function as parameter where you can implement your logic. In summary you should do the following:

  • Inject the Platform service inside the Foo component.
  • Call the registerBackButtonAction in the ngOnInit (or another init method) and pass a function callback as parameter that executes the logic to close the modal (this.modalController.dismiss();)
  • Clear the action when the modal component is closed (for example in ngOnDestroy method). To do that, the registerBackButtonAction returns a function that when is called the action is removed.

The code should be something like:

constructor(private platform: Platform) {
    ...
}

ngOnInit() {
    this.unregisterBackAction = this.platform.registerBackButtonAction(() => {
        this.modalController.dismiss();
    })
}

ngOnDestroy() {
    if(this.unregisterBackAction) this.unregisterBackAction();
}

Upvotes: 3

Related Questions