Reputation: 1292
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
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
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
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
Reputation: 129
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
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
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
Reputation: 191
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:
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();
)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