Skip to content

servrox/demo-ionic-tabs-back-button

Repository files navigation

Demo: Ionic tabs + global pages with ion-back-button

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.

Live Demo

Getting Started

git clone https://github.com/servrox/demo-ionic-tabs-back-button.git cd demo-ionic-tabs-back-button yarn ionic serve 

Solutions shown in demo

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.

1. Passing previous page (s. global-page-one)

This solution overcomes the problem by using an ion-button instead of the ion-back button.
To make it work following steps are necessary:

  1. Get the route you want to navigate back later.
this.currentRoute = btoa(this.router.url); 
  1. 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> 
  1. 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; 
  1. 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)

  1. Install from npm
npm i ion-back-button-tabs --save 
  1. 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 { } 
  1. 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 {} 
  1. Use ion-back-button-tabs in template
<ion-back-button-tabs defaultHref="/tabs/tab1" tabsPrefix="tabs" tabsPageSelector="app-tabs"> </ion-back-button-tabs> 

Problem explained

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.

Built With

Authors