Close Modal in Ionic 4 by Back Button - modal-dialog

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.

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();
}

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();
}

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();
}
}
});

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.

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() }
});
}

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.

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

Related

I want to passing id (stored in firestore) from page to another page in ionic4 App

i want to passing ID that i stored it in Firestore database from page to another page in my Ionic4 App
i have news app that i retrieved the contents from firestore and i want when i click on the news it must show the details in details page
my code in briefly :
news.page.html
<ion-content padding>
<ion-item *ngFor=" let count of data">
<h5>{{count.title}}<ion-button (click)="goToDetail()">click for details</ion-button>
<img src="{{count.image}}">
</h5>
</ion-item>
news.page.ts
export class FilmsPage implements OnInit {
data: any;
constructor(public db: AngularFirestore, private router: Router) { }
ngOnInit() {
this.getAllPosts().subscribe((data) => {
this.data = data;
console.log(data);
});
}
getAllPosts(): Observable<any> {
return this.db.collection<any>('123').valueChanges ();
}
goToDetail() {
this.router.navigateByUrl('/details/{{count.id}}');
}
}
details.page.ts
export class DetailsPage implements OnInit {
id: string;
constructor(private router: ActivatedRoute, private afs: AngularFirestore) {
}
ngOnInit() {
this.id = this.router.snapshot.paramMap.get('id');
console.log(this.id);
}
}
details.page.html
<ion-content padding>
{{id}}
</ion-content>
but when i run this code its just showed {{count.id}} in details.page.html .. why??? can somone solve this probllem please
If the details.page is to be view in modal then I think you can you can pass the data to the ModalController to view the new
The best solution is to use a ModalController to pass the single news data to the details.page.

Side menu not opening on the page opened via button on modal

I am developing an ionic app with a side menu.
In my app, i added a modal that contains three button. When i click on any button in that modal, it opens a new page. On that new page, i have header containing a button that is used to open the side menu.
Problem
Side menu opens normally on any page that isn't opened via buttons on modal but when i try to open the side menu on a page that was opened via button on a modal, instead of opening the side menu on that page, it opens the side menu behind the current page and when i press back button to go back to previous page, side menu can be seen opened on the previous page.
Question
What is causing this behavior and how can i fix it ?
Custom Modal typescript code
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams, ViewController } from 'ionic-angular';
import { LibraryPageSerice } from './libraryPage.service';
#IonicPage()
#Component({
selector: 'page-custom-posting-pop-up',
templateUrl: 'custom-posting-pop-up.html',
})
export class CustomPostingPopUpPage {
onLibraryPage: boolean;
constructor(private navCtrl: NavController, private navParams: NavParams,
private viewCtrl: ViewController,
private libService: LibraryPageSerice) {}
ionViewDidLoad() {
this.onLibraryPage = this.libService.onLibraryPage;
}
dismissModal(event) {
if(event.target.className === 'modal-container') {
this.viewCtrl.dismiss();
}
}
openCreationpage() {
this.viewCtrl.dismiss();
this.navCtrl.push('PostingCreationPage');
}
openSupportivePage() {
this.viewCtrl.dismiss();
this.navCtrl.push('PostingSupportivePage');
}
openLibraryPage() {
this.viewCtrl.dismiss();
this.navCtrl.push('MylibraryPage');
}
}
Custom modal html code
<div class="modal-container" (click)="dismissModal($event)">
<div class="modal">
<p>Posting Method</p>
<div class="btn-container">
<button class="creation-btn" (click)="openCreationpage()">My Creation</button>
<button class="supportive-btn" (click)="openSupportivePage()">Supportive</button>
<button *ngIf="!onLibraryPage" class="library-btn" (click)="openLibraryPage()">
My Library
</button>
</div>
</div>
</div>
This method is used to open the modal
posting() {
const modal = this.modalCtrl.create('CustomPostingPopUpPage');
modal.present();
}
If i don't use the modal and instead use an alert dialog to open the new page, side menu opens normally. So this problem only arises when i use a modal.
This is part of how modals are defined to work, "A Modal is a content pane that goes over the user's current page ... A modal uses the NavController to present itself in the root nav stack"
Because of this when you are calling this.navCtrl.push('PageName'); this instance of NavController is an Overlay Portal whereas a normal NavController not from a modal is a Nav. This will cause the page to be pushed along side your app-root (Which causes the results that you are witnessing).
Here are two solutions to this.
Pass in reference of NavController to your modal using NavParams
// home.ts
let modal = this.modalCtrl.create('ModalPage', {'nav': this.navCtrl});
// modal.ts
nav: Nav;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public viewCtrl: ViewController) {
this.nav = this.navParams.get('nav');
}
openSupportivePage() {
this.viewCtrl.dismiss();
this.nav.push('PostingSupportivePage');
}
Or pass which page you want to open to viewCtrl.dismiss() and parse with onDidDismiss
// home.ts
modal.onDidDismiss((open_page) => {
if (open_page !== undefined && open_page.hasOwnProperty('open_page')) {
this.navCtrl.push(open_page['open_page']);
}
});
// modal.ts
openCreationpage() {
this.viewCtrl.dismiss({'open_page': 'PostingCreationPage'});
}

Ionic 3 - modal backdrop does not work

I want my modal pops up (with backdrop) rather than a new page. I followed some tutorials but the backdrop is not working (it should be activated by default). I am sure I am missing something.
Here the code from the page where the modal is opened.
openPhonesModal(){
const myModalOptions: ModalOptions = {
showBackdrop: true,
enableBackdropDismiss: false
};
const myModalData = {
phone1: '01 239 239',
phone2: '901 200 438'
};
const myModal: Modal = this.modal.create('ModalseephonesPage',{phones:
myModalData},myModalOptions);
myModal.present();
}
Here the code of the modal itself:
export class ModalseephonesPage {
constructor(private navParams: NavParams, private view: ViewController) {
}
ionViewWillLoad() {
const phones = this.navParams.get(‘phones’);
console.log(phones);
}
closeModal(){
this.view.dismiss();
}
}
I hope I provided enough information.
Thank you in advance.

Close login modal after register modal

Is there a way within Ionic to close a specific modal? Right now my flow is that I open a login modal and then the user can create an account which opens another modal. Upon successful signup, they get logged in and both modals should close but I'm only able to get the register closed.
this.closeModal();
this.viewCtrl.dismiss('LoginPage');
The second line does nothing. How would I dismiss the second modal after the first one closes? Any help would be great, thanks!
Pass a value success from the registration page. And on the login page access the value. If it is success then this.viewCtrl.dismiss().
Yiu have to dismiss the view in both pages.
You could return a result from the SignUpPage (true if the user was able to signup successfully), and check it in the SignInPage, to see if that modal should also be closed. It'd look like this:
#Component({
selector: 'page-sign-in',
templateUrl: 'sign-in.html'
})
export class SignInPage {
constructor(private viewCtrl: ViewController, private modalCtrl: ModalController) {}
// ...
// Method that redirects the user to the SignUpPage
public openSignUp(): void {
let modal = this.modalCtrl.create('SignUpPage');
modal.onDidDismiss(success => {
if (success) {
// Since this is also a modal, we should dismiss this view
this.viewCtrl.dismiss();
}
});
modal.present();
}
}
And...
#Component({
selector: 'page-sign-up',
templateUrl: 'sign-up.html'
})
export class SignUpPage {
constructor(private viewCtrl: ViewController) {}
// ...
// Method that redirects the user to the SignUpPage
public signUp(): void {
//...
// Return true if the user was able to sign up
this.viewCtrl.dismiss(true);
}
public close() {
// Close only this modal, but not the SignInPage modal
this.viewCtrl.dismiss(false);
}
}
The simplest solution to my problem was to just close one modal before opening another one.

ionic 2 3, why after scrolling, value of variable doesn't change?

I was wrote this code for showing button after scrolling is more than 500px, but "showButton" didn't get new value.
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton">Scroll Top</button>
</ion-content>
my.ts file:
showButton= false;
onScroll($event) {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton= true;
}
}
This console.log shows change of "showButton", but in html it doesn't change.
"showButton" for first time get value "false" but when value change to "true" it can not listen to change, how I can solve this?
From the ionic docs, Scroll Events Scroll events happen outside of
Angular's Zones. This is for performance reasons. So if you're trying
to bind a value to any scroll event, it will need to be wrapped in a
zone.run()
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton">Scroll Top</button>
</ion-content>
//add import in .ts file
import { Component, NgZone } from '#angular/core';
//in constructor
constructor(
public zone: NgZone,
showButton= false;
onScroll($event) {
this.zone.run(() => {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton = true;
}
})
}
//Method 1) use boolean variable
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton">Scroll Top</button>
</ion-content>
showButton:boolean= false;
onScroll($event) {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton= true;
}
}
OR
//Method 2) use number variable
<ion-content (ionScroll)="onScroll($event)">
<button *ngIf="showButton==1">Scroll Top</button>
</ion-content>
showButton:number= 0;
onScroll($event) {
if ($event.scrollTop > 500) {
console.log(this.showButton);
this.showButton= 1;
}
}