Ionic 4 project with a tab based layout and workarounds for the ion-back-button
.
The demo shows two ways how to navigate from a tabbed page to a 'global' page and back,
without losing tab-states.
git clone https://github.com/servrox/demo-ionic-tabs-back-button.git
cd demo-ionic-tabs-back-button
yarn
ionic serve
First solution is a workaround that overcomes the problem.
The second one is a fix which deals directly with the problem
by using ion-back-button-tabs
a custom ionic 4 component.
This solution overcomes the problem by using an ion-button
instead of the ion-back button
.
To make it work following steps are necessary:
- Get the route you want to navigate back later.
this.currentRoute = btoa(this.router.url);
- Pass that value to the page called. (url params used here)
<ion-button
[routerLink]="['/global-page-one', {p: currentRoute}]"
routerDirection="forward">
Global Page One
</ion-button>
- On the page called check if a route was given
this.previousPage = this.route.snapshot.paramMap.get('p') ? atob(this.route.snapshot.paramMap.get('p')) : null;
- Use given route when user clicks back
back() { this.navCtrl.navigateBack(this.previousPage); }
To make the ion-button
look exactly like the ion-back-button
, you can check which platform is being used.
this.showText = this.plt.is('ios');
If the page with the back-button is the first page called, the real ion-back-button
can be used. This works because then the defaultHref is taken.
this.router.events.subscribe((event: RouterEvent) => {
if (event instanceof NavigationEnd) {
this.useRealBackButton = event.id === 1;
}
});
Final solution looks like this in template:
<ion-buttons slot="start">
<ion-back-button *ngIf="useRealBackButton"
[defaultHref]="previousPage ? previousPage : '/tabs/tab1'">
</ion-back-button>
<ion-button *ngIf="!useRealBackButton" (click)="back()">
<ion-icon name="arrow-back"></ion-icon>
{{ showText ? 'Back' : null }}
</ion-button>
</ion-buttons>
In this solution swiping back (iOS gesture) is disabled for the particular page.
ngOnInit() { this.routerOutlet.swipeGesture = !this.plt.is('ios');
[...]
ionViewDidLeave() { this.routerOutlet.swipeGesture = this.plt.is('ios'); }
ion-back-button-tabs
supports swiping back! (see below)
2. Using ion-back-button-tabs
component (s. global-page-two)
- Install from npm
npm i ion-back-button-tabs --save
- Import
BackButtonTabsModule
to the page module (global-page-two.module.ts)
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { GlobalPageTwoPage } from './global-page-two.page';
import { BackButtonTabsModule } from 'ion-back-button-tabs';
const routes: Routes = [
{
path: '',
component: GlobalPageTwoPage
}
];
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
RouterModule.forChild(routes),
BackButtonTabsModule
],
declarations: [GlobalPageTwoPage]
})
export class GlobalPageTwoPageModule { }
- Get attributes for
ion-back-button-tabs
tabsPrefix
is the url path set for the TabsPage component (e.g. 'tabs')
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TabsPage } from './tabs.page';
const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'tab1',
children: [
{
path: '',
loadChildren: '../tab1/tab1.module#Tab1PageModule'
}
]
},
{
path: 'tab2',
...
tabsPageSelector
is the selector of the TabsPage component (e.g. 'app-tabs')
import { Component } from '@angular/core';
@Component({
selector: 'app-tabs',
templateUrl: 'tabs.page.html',
styleUrls: ['tabs.page.scss']
})
export class TabsPage {}
- Use
ion-back-button-tabs
in template
<ion-back-button-tabs
defaultHref="/tabs/tab1"
tabsPrefix="tabs"
tabsPageSelector="app-tabs">
</ion-back-button-tabs>
When navigating from a page inside a tab to a 'global' page,
the ion-back button
will no longer work properly.
More specifically, the back button no longer navigates to the previously opened page, instead it uses the redirect of the tabs-routing.
This happens because the ion-back-button
uses only the main-IonRouterOutlet, instead of also checking tabs-IonRouterOutlet.
Which means that the StackController inside the main-IonRouterOutlet only knows the route of the tabs module (e.g. 'tabs').
^No guarantee on this^
Problem is also described in the official Bug Report.
- Ionic CLI - version 4.10.3
- Ionic Framework - @ionic/angular 4.0.1
- Marcel Mayer - servrox.solutions