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