Ionic-framework: [Ionic v4-beta.3] Bug navigation between tab page & no page tab - back button redirects to wrong tab

Created on 17 Aug 2018  路  58Comments  路  Source: ionic-team/ionic-framework

Bug Report

Ionic Info

Ionic:

   ionic (Ionic CLI)          : 4.1.0 (/usr/local/lib/node_modules/ionic)
   Ionic Framework            : @ionic/angular 4.0.0-beta.3
   @angular-devkit/core       : 0.7.0-rc.3
   @angular-devkit/schematics : 0.7.0-rc.3
   @angular/cli               : 6.0.8
   @ionic/ng-toolkit          : 1.0.0
   @ionic/schematics-angular  : 1.0.1

Cordova:

   cordova (Cordova CLI) : 7.1.0
   Cordova Platforms     : ios 4.5.5
   Cordova Plugins       : cordova-plugin-ionic-keyboard 2.1.2, cordova-plugin-ionic-webview 2.0.2, (and 4 other plugins)

System:

   ios-deploy : 1.9.2
   ios-sim    : 6.1.1
   NodeJS     : v10.6.0 (/usr/local/bin/node)
   npm        : 6.4.0
   OS         : macOS High Sierra
   Xcode      : Xcode 9.4.1 Build version 9F2000

Describe the Bug
I have an application with a tabs ( 5 pages home, search, map , info and tarif).
From the search page i can go on a non-tab page like this this.router.navigate(['station'], { queryParams: station});
On the station page i have a back button to return to the search page <ion-back-button text=""></ion-back-button>
The back button disappear at the second time.
Here are some additional informations:

tabs.router.module.ts

const routes: Routes = [
  {
    path: 'tabs',
    component: TabsPage,
    children: [
      {
        path: 'home',
        outlet: 'home',
        component: HomePage
      },
      {
        path: 'search',
        outlet: 'search',
        component: SearchPage
      },
      {
        path: 'map',
        outlet: 'map',
        component: MapPage
      },
      {
        path: 'info',
        outlet: 'info',
        component: InfoPage
      },
      {
        path: 'tarif',
        outlet: 'tarif',
        component: TarifPage
      }
    ]
  },
  {
    path: '',
    redirectTo: '/tabs/(home:home)',
    pathMatch: 'full'
  }
];

app-routing.module.ts

const routes: Routes = [
  { path: '', loadChildren: './tabs/tabs.module#TabsPageModule' },
  { path: 'map', loadChildren: './map/map.module#MapPageModule' },
  { path: 'search', loadChildren: './search/search.module#SearchPageModule' },
  { path: 'station', loadChildren: './station/station.module#StationPageModule' },
  { path: 'info', loadChildren: './info/info.module#InfoPageModule' },
  { path: 'tarif', loadChildren: './tarif/tarif.module#TarifPageModule' }
];

i don't know if it's my bad or a bug ?

Steps to Reproduce
Steps to reproduce the behavior:

  1. Click on tab menu to go to search page
  2. From search page go to station page ( a non-tab page)
  3. Go back to search page with back button
  4. Click on the same station to go on station page
  5. The back button disappear, i can't go back on search page

Expected Behavior
Fix nav when i from a non-tab page

Additional Context
I have a log when i go to the station page at the second time
ion-router-outlet.js:32 router-outlet destroyed

And i have an another issue, how i can conserve the tab menu on my station page ?

angular bug

Most helpful comment

Let's make my summarize the issue:

  • You leave the tabs section on tab User with routerDirection="forward"
  • Now you want to go back
  • You will send back to tab 1 (Home) - not to User where you left the tabs

2019-01-15_10-55-14

  • The reason: The url is only tabs, not the last tab page you visited

chrome_2018-12-14_15-06-24

So this route is matching:

      {
        path: '',
        redirectTo: '/tabs/home',
        pathMatch: 'full',
      },

And the user will be redirect to home instead of tabs/user

This is based on https://github.com/lampi87/ionic-bug-test (you have to add the redirect route again to see the issue). This repo has not the redirect route, so the user stays on User where he left the tabs

All 58 comments

Note that this sample app: https://github.com/kensodemann/test-prolea which I created to demo a different but related issue (#14861) also shows this behavior if the person picking this up needs a sample app to reproduce this.

same issue here: router-outlet destroyed

any news on that?
I took a look at the ionic-conference app because it's working there.
Interesting implementation..

Same issue here. Navigating from a subpage backwards lands on the first tab instead the last selected.

More: https://stackoverflow.com/questions/52268092/navigate-back-to-tab-index-with-ionic-4/52268576#52268576

Any update on this ?

I'm still having the same issue.

It seems this issue is still unresolved

Same here, the router-outlet destroyed issue makes the page transition becomes rude, without animation (at least in ios).

Simple reproduce:

  • Create page with tabs
  • In first tab (say, home tab), create list of items.
  • Set the item's href to item detail page.
  • Click it, and you'll be redirected to the detail page.
  • Now refresh browser, you will stay in detail page.
  • Press ion-back-button (with defaultHref). You'll be moved to home tab.
  • Now from home tab, click on that item again, and the issue will occur.

Update:
For my case, this issue is solved by setting routerDirection="forward" to my items in home tab.

I solved the problem by navigate with ionic NavController instead of angular router
I changed the following line:

this.router.navigateByUrl(url)

to

this.navController.navigateForward(url)

I solved the problem by navigate with ionic NavController instead of angular router
I changed the following line:

this.router.navigateByUrl(url)

to

this.navController.navigateForward(url)

Does not work for me

I'm still having the same issue.

removing routerDirection fixed the issue for me. No more router-outlet destroyed. Dobby is a free elf

Same for me.
Neither navCtrl.navigateForward, nor router.navigateByUrl works for me

this.navCtrl.goBack();
worked for me;
it is like subsitute to this.navCtrl.pop();
in ionic 4

The "router-outlet destroyed" issue is a pain and we mixed it up with a tab problem on our side. The "router-outlet destroyed" appears, navigation between child pages:

https://forum.ionicframework.com/t/ionic-4-navigate-between-child-routes-router-outlet-destroyed/149902
!

We've released beta.18 now with another refactor of tabs. Could you check if the issue is fixed? Please keep in mind the breaking changes: https://github.com/ionic-team/ionic/blob/master/CHANGELOG.md#400-beta18-2018-12-13

Unfortunately issue is still reproducible for me.
Page structure:
Page 'test' defined in app-routing.module.ts
Tab 1 (no childs)
Tab 2 (no childs)
Tab 3, one child
If I change to Tab 3 -> Tab 3 child and click on ion-button to open page, e.g /test1, via routerLink. On click on the page /tabs/tab1 is opened
Same issue if tab 3 has no childs and page /test is opened. On clicking back button, tab1 is opened

Then please create a repo so we can take a look at it

You can find repo at: https://github.com/lampi87/ionic-bug-test
There are 3 pages in tabs "home", "calendar" and "user". On user page a button is shown to open "/settings" page. This page is intended to be shown without tabs at bottom. If you press back button on settings page, "home" is opened instead of "user"

Ah okay, as you said:

This page is intended to be shown without tabs at bottom.

This will be the issue because you will destroy the tabs (I did not watch into your repo yet, but I think this will be happen) and if you want to go back, he creates the tab component again and so you start at the first page.

There are two ways:

1) Don't destroy the tabs component on switching (this will only work if the router will be not destroyed and you navigate forward)

2) Save the current tab and if the user switches back send him to this tab

@manucorporat or do you have another idea for this use case?

How is it possible to open a page without tabs and not to destroy the router?
It wasn't my intention to destroy the tabs component on switching

I tested it and yes, it's working. If you are using routerlink, just add routerDirection="forward":

    <ion-item [routerLink]="p.link"  [routerDirection]="'forward'" routerLinkActive="highlight" [routerLinkActiveOptions]="{ exact: true }" color="primary" lines="none"
      button>
      <ion-icon [name]="p.icon" slot="start"></ion-icon>
      <ion-label text-wrap>{{p.title | translate}}</ion-label>
    </ion-item>

PS: My snippet contains some content from my app, so you cannot copy it 1:1 in your app. Your router outlet mustn't be destroyed!

I've updated my repo (https://github.com/lampi87/ionic-bug-test) and issue is still reproducible
I tried to open page with
<ion-button color="primary" expand="block" routerLink="/settings" routerDirection="forward">Settings</ion-button>
and
<ion-button color="primary" expand="block" routerLink="/settings" [routerDirection]="'forward'">Settings</ion-button>
but on ion-back-button tab1 is opened.

Let's make my summarize the issue:

  • You leave the tabs section on tab User with routerDirection="forward"
  • Now you want to go back
  • You will send back to tab 1 (Home) - not to User where you left the tabs

2019-01-15_10-55-14

  • The reason: The url is only tabs, not the last tab page you visited

chrome_2018-12-14_15-06-24

So this route is matching:

      {
        path: '',
        redirectTo: '/tabs/home',
        pathMatch: 'full',
      },

And the user will be redirect to home instead of tabs/user

This is based on https://github.com/lampi87/ionic-bug-test (you have to add the redirect route again to see the issue). This repo has not the redirect route, so the user stays on User where he left the tabs

We're facing the very same issue on iOS.
Is there any ETA on this?
It makes the whole app completely unreliable.

Still an issue in 4.0.0-rc.1

i developing app in ionic4, i have latest cli 4.8.
i am facing same issue, i have 3 page.
page1, page2, page3.
i go to page1>page2>page3.
now if i use only hardware button then it working well, if i use only back button of app then its also working well.

but if i use app back button for page3 to page2 and after that i used hardware back button then it go to page3 instant of page1.
and in page3 app back button is hide.

+1 facing same issue

Not sure if this is the solution, but it worked for me.

Ionic CLI adds the child page to app-routing.module.ts instead of tabs.router.module. Makes sense since Ionic CLI wouldn't know if you have tabs or not. (or does it?)

I removed { path: 'station', loadChildren: './station/station.module#StationPageModule' } from app-routing.module.ts and nested it under the corresponding tab in tabs.router.module

Referencing the original post, it'd look something like this

{
        path: 'search',
        outlet: 'search',
        component: SearchPage,
        children: [
          {
            path: 'station',
            loadChildren: './station/station.module#StationPageModule' }
          }
        ]
      },

I also had to update the router link to /tabs/search/station from ,in this case, the ion-item on the station page or the .ts page.

Now it should go 'back' to the tab it came from.

Thanks for the issue! There were made some changes in the latest commits (#17182) - just install the latest dev build (npm install @ionic/[email protected]).

If you want to overwrite the default behaviour, you can also use:
this.platform.backButton.subscribeWithPriority(9999, () => { // You decide what happens });
Using hardware back button , go to back page, close menu, close alert, close action sheet, close toast, close popover, close model etc add this code app.component.ts

hardwareBackButton() { let options: NativeTransitionOptions = { direction: 'right', duration: 500, slowdownfactor: 3, androiddelay: 150 }; this.platform.backButton.subscribeWithPriority(9999, async () => { // close toast try { const element = await this.toastController.getTop(); if (element) { element.dismiss(); return; } } catch (error) {} // close alert try { const element = await this.alertController.getTop(); if (element) { element.dismiss(); return; } } catch (error) {} // close action sheet try { const element = await this.actionSheetCtrl.getTop(); if (element) { element.dismiss(); return; } } catch (error) {} // close popover try { const element = await this.popoverCtrl.getTop(); if (element) { element.dismiss(); return; } } catch (error) {} // close modal try { const element = await this.modalCtrl.getTop(); if (element) { element.dismiss(); return; } } catch (error) { console.log(error); } // close side menua try { const element = await this.menu.getOpen(); if (element) { this.menu.close(); return; } } catch (error) {} if (this.router.url == '/startmain' || this.router.url == '/home') { if (this.lastTimeBackPress == 0) { const toast = await this.toastController.create({ message: 'Press back again to exit App.', position: 'bottom', duration: 2000, color: 'medium', animated: true, mode: 'ios' }); await toast.present().then(() => { this.lastTimeBackPress = 1; }); let TIME_IN_MS = 4000; let hideFooterTimeout = setTimeout(() => { // somecode this.lastTimeBackPress = 0; }, TIME_IN_MS); } else { navigator['app'].exitApp(); // work in ionic 4 } } else if (this.routerOutlet && this.routerOutlet.canGoBack()) { this.nativePageTransitions.slide(options); this.routerOutlet.pop(); } else { // this.platform.exitApp(); // Exit from app navigator['app'].exitApp(); // work in ionic 4 } }) }

Add this.hardwareBackButton(); after this.initializeApp(); for call upper fuction
Thanks

@aftabkhatri Did you even read what @paulstelzer wrote? Without redirect everything works, but what about redirect? When the user goes to the/tabs page, the page is blank. @paulstelzer knows what the issue is.

I think you get confused and you are discussing another issue.

Removed redirectTo from tabs routes looks like a fix for this issue, but it caused another issue, there's no route for ''. So I don't think it's a real fix

We are having this issue here as well. If I initiate the navigation outside the Tabs router or navigate to a page that is outside of the Tabs router I cannot access the pages nested over the Tabs router.

The only solution that worked for us is to nested all the pages inside the Tabs and hide the ion-tab-bar on the pages I don't want it to appears.

Of course, this is far from the ideal solution but it's a good way to work around this.

We are having this issue here as well. If I initiate the navigation outside the Tabs router or navigate to a page that is outside of the Tabs router I cannot access the pages nested over the Tabs router.

The only solution that worked for us is to nested all the pages inside the Tabs and hide the ion-tab-bar on the pages I don't want it to appears.

Of course, this is far from the ideal solution but it's a good way to work around this.

No, you don't have to do this. You can just not use ion-back-button, instead you add a normal button, a back style, and call navCtrl.back() in the click event. Then you get your expectation

<ion-button (click)="navCtrl.back()">
        <ion-icon slot="icon-only" name="arrow-round-back" color="dark"></ion-icon>
</ion-button>

@qiluo I also thought for a long time why ionic uses the method nav.pop(), instead nav.back() method. ion-back-button.ts:L26

nav.pop();
This is the recommended way to go back when you are using ion-router-outlet

nav.back();
It will use the standard window.history.back() under the hood, but featuring a back animation.

Ps: Why not use the window.history.back() method, or maybe as it was tested and decided to use the nav.pop() method. In general, we will wait for an official response.

@bossjon, it's routerOutlet.pop(), not nav.pop(), is there any difference?

Actually I tried nav.pop(), it caused weird navigation in my app, meanwhile nav.back() work around anyway. Wait for official fix

Maybe my explanation + code helps here (before creating the demo I stumbled on this post).

I expirienced same cause I didn't define the continuing routes in the child-block.
Routing may seem to work, but things like ion-back-button are fucked up.

The demo is using the ion-back-button and shows different approaches for route definition.
Unlike the code above I used lazy loading for every page.

@servrox, The way you did, it works, but we're talking about pages with no tabs. Like a global page that can be opened anywhere, and you can go back.

I'm still having the same issue.

This is a moment fix for me
controller
back() { this.router.navigate(['tabs/tab1']); }
html
<ion-buttons slot="start"> <ion-back-button (click)="back()"></ion-back-button> </ion-buttons>

@paul-landaeta-tierconnect-com, The user can open the page from any tab or any other page, and how will you define the back url?
ion-back-button is created for this.

In tabs.router.module.ts change this:

const routes: Routes = [ { path: 'tabs', component: TabsPage, children: [ ... { path: '', redirectTo: '/tabs/tab1', pathMatch: 'full' }

for this (remove /tab1):

{ path: '', redirectTo: '/tabs', pathMatch: 'full' }

This solves the back button of the topbar as the physical of android. It works well for me.

Live Demo

@bossjon I have created a second demo project covering the case with global pages.

@paul-landaeta-tierconnect-com When you navigating back like this, you will lose the state inside your tabs. This is because internally it navigates back to /tabs and then to the route specified in your back() function. See my solutions to navigate back without losing tab-states.

_Direct link to my advanced ion-back-button component._

I can confirm the issue described in the gif by @paulstelzer in Ionic 4.0.2.

@servrox, Thanks for the answer. Your option works, but when you navigate back (swipe) on iOS, then the ion-router-outlet.ts#L197 or stack-controller.ts#L78 function runs. Because of this, your solution does not work, I think the (ionic) developers will notice your decision and fix the navigation. @paulstelzer

Ps: I also thought for a long time how to add a custom version of the navigation to the application, but I could not find a way.

@bossjon uh ur right 馃憤馃徎 completely forgot about navigation back via swipe gesture..
I added this case to my demo.

ion-back-button-tabs fully support swipe gestures now!
For the workaround it seemed easiest to disable the gesture for the particular page.

@servrox I think this issue is not in the priority of the ionic team, but this issue makes the tabs unnecessary. I also tried a lot of ways like you, but I don鈥檛 want to write another component for this and maintain it.
Thanks again for the proposed solution to this issue.

The problem is present in Ionic 4.1.1 but @TioChachi29 workaround works for me, it sounds simple and I don't need to change html or ts files, so I can rearrange code (this already happened) without problems.
Honestly I don't understand if this can create some side effect

@dafi yes, if it has a side effect, when ionic serve is executed on some occasions the content of the tabs is not displayed, but when executing it in Android or in iOS this does not happen. I do not know if there is another problem.

@TioChachi29 if the problem occurs only with ionic serve I can tolerate it, thanks for the hint

In tabs.router.module.ts change this:

const routes: Routes = [ { path: 'tabs', component: TabsPage, children: [ ... { path: '', redirectTo: '/tabs/tab1', pathMatch: 'full' }

for this (remove /tab1):

{ path: '', redirectTo: '/tabs', pathMatch: 'full' }

This solves the back button of the topbar as the physical of android. It works well for me.

Its solved the issue, Thanks

In tabs.router.module.ts change this:

const routes: Routes = [ { path: 'tabs', component: TabsPage, children: [ ... { path: '', redirectTo: '/tabs/tab1', pathMatch: 'full' }

for this (remove /tab1):

{ path: '', redirectTo: '/tabs', pathMatch: 'full' }

This solves the back button of the topbar as the physical of android. It works well for me.

It solves the issue, but the url is the wrong one at the top, it's the root tab url (/tabs in my case). Also if you tap the current tab, it tries to load the root tab url.

In tabs.router.module.ts change this:

const routes: Routes = [ { path: 'tabs', component: TabsPage, children: [ ... { path: '', redirectTo: '/tabs/tab1', pathMatch: 'full' }

for this (remove /tab1):

{ path: '', redirectTo: '/tabs', pathMatch: 'full' }

This solves the back button of the topbar as the physical of android. It works well for me.

Thanks!
It solves the issue but if you navigate forward to /tabs it will not select the default tab. So, you'll have always to specify the full url of the default tab (/tabs/tab1 or whatever).

Hi everyone,

I have opened a PR that should resolve this issue: https://github.com/ionic-team/ionic/pull/18005

One of my colleagues will be reviewing it soon, but in the meantime if anyone would like to take a look and provide feedback, that would be great!

We appreciate your patience as we work to resolve this issue 馃檪

Hi there,

This issue has been resolved, and I have published a nightly build of Ionic with the fix. You can install it with npm i @ionic/angular@dev.

Please let me know if you are still running into any issues with this.

Thanks!

@liamdebeasi hi!

Thank you for the fix. What about navigation back (pop) programmatically? When I call navCtrl.pop from a nested outlet which is not in a tab, it redirects back to the right tab which has some nav stack, but then navCtrl.pop doesn't work. With ion-back-button it works fine after fix.

Hi there,

Please open a new Bug Report for this issue.

Thanks!

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

giammaleoni picture giammaleoni  路  3Comments

gio82 picture gio82  路  3Comments

fdnhkj picture fdnhkj  路  3Comments

manucorporat picture manucorporat  路  3Comments

masimplo picture masimplo  路  3Comments