Hardware backbutton Issue with ion-tabs

I have an app with 3 tabs. The main one has a list of items that when clicked open a page with item details.
I’m using this code below to exit the app when the hardware back button is pressed on Android:

import { Component, ViewChild } from '@angular/core';
import { Platform, IonRouterOutlet } from '@ionic/angular';
import { App } from '@capacitor/app';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {

  @ViewChild(IonRouterOutlet, { static : true }) routerOutlet: IonRouterOutlet;

  constructor(private platform: Platform) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(async () => {

      App.addListener('backButton', () => {
        if (!this.routerOutlet.canGoBack()) {
          App.exitApp();
        }
      });

    });
  }
}

When I navigate to a item detail page and hit the backbutton, this.routerOutlet.canGoBack() is always returning false, and so exiting the app.

My list loop is like this:

<ion-item *ngFor="let i of items" [routerLink]="['/','items',p.Id]">

The tabs html are located at route ‘/items’ and the items list is located at ‘/ordinary’.

tabs.html:

<ion-tabs>
  <ion-tab-bar>

    <ion-tab-button tab="ordinary">
      <ion-label>Ordinary Items</ion-label>
      <ion-icon name="pricetag-outline"></ion-icon>
    </ion-tab-button>
    
  </ion-tab-bar>
</ion-tabs>

My items-routing.module.ts:

const routes: Routes = [

  {
    path: '',
    component: ItemsPage,
    children: [
     {
        path: 'ordinary',
        children: [
          {
            path: '',
            loadChildren: () => import('./ordinary/ordinary.module').then(m => m.OrdinaryPageModule)
          }
        ]
      },      
      {
        path: ':itemId',
        loadChildren: () => import('./details/details.module').then(m => m.OrdinaryPageModule)
      },
      {
        path: '',
        redirectTo: '/items/ordinary',
        pathMatch: 'full'
      }
    ]
  },
  {
    path: '',
    redirectTo: '/items/ordinary',
    pathMatch: 'full'
  }
];

Maybe this.routerOutlet.canGoBack() is returning false because the details page path is ‘items:itemId’, effectively ‘items/id’? Or maybe something else I can’t see?

Any luck figuring this out? Just ran into same issue. routerOutlet.canGoBack works fine in a non-tabbed app, but with tabs, always returns false…

I took a closer look at the problem and it seems that routerOutlet always fetches the next instance of ion-router-outlet from the respective page.
So if we call routerOutlet.canGoBack() inside app.component.ts, the value would always be false because the ion-tabs have their own ion-router-outlet.

Thats why using this.routerOutlet.canGoBack() inside some childpages of ion-tabs will return the correct boolean value.

If you need to handle something globaly (like using android hardware backbutton to exit app) you can use following snippet:

@ViewChild(IonTabs, { static: true }) private ionTabs: IonTabs;
...
constructor(
  private platform: Platform,
) {
  this.platform.backButton.subscribeWithPriority(-1, () => {
    if (!this.ionTabs.outlet.canGoBack()) {
      App.exitApp();
    }
  });
}

It’s important that you handle the logic inside tabs.page.ts since we use the Viewchild of ìon-tabs`, which contains the outlet for tabbed pages.

I also documented this on this ionic issue