ionic-framework: ion-back-button does not work correctly together with angular router navigate option "replaceUrl" (V4)

Bug Report

Ionic Info Run ionic info from a terminal/cmd prompt and paste the output below.

Ionic:

   ionic (Ionic CLI)          : 4.0.1 
   Ionic Framework            : @ionic/angular 4.0.0-beta.2
   @angular-devkit/core       : 0.7.3
   @angular-devkit/schematics : 0.7.3
   @angular/cli               : 6.1.3
   @ionic/ng-toolkit          : 1.0.6
   @ionic/schematics-angular  : 1.0.4

Cordova:

   cordova (Cordova CLI) : 7.0.1
   Cordova Platforms     : none

System:

   Android SDK Tools : 26.0.2
   NodeJS            : v8.11.3 (C:\Program Files\nodejs\node.exe)
   npm               : 6.2.0
   OS                : Windows 7

Environment:

   ANDROID_HOME : D:\Android\sdk

Describe the Bug ion-back-button does not work correctly together with angular router replaceUrl option

Steps to Reproduce if i navigate from “/home” to “/login” and then navigate to “/pageC” by setting: this.router.navigate([“/pageC”], {replaceUrl:true});

the browser back button correctly take me back to “/home” instead of "/login " but ion-back-button still take me back to “/login”

Related Code If you are able to illustrate the bug with an example, please provide a sample application via an online code collaborator such as StackBlitz, or GitHub.

Expected Behavior ion-back-button should take me back to “/home” instead of "/login " while the angular router option replaceUrl is set to “true”

Additional Context List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, screenshots, OS if applicable, etc.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 9
  • Comments: 24 (6 by maintainers)

Commits related to this issue

Most upvoted comments

The way I’ve overcome this issue:

  1. Created a custom directive:
import {Directive, HostListener} from '@angular/core';
import {Location} from '@angular/common';

@Directive({
  selector: '[app-location-back]'
})
export class LocationBackDirective {
  constructor(private location: Location) { }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    this.location.back();
  }
}
  1. Used the directive’s selector as a property on my ion-button:
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-button app-location-back fill="clear">
         <ion-icon name="arrow-back" slot="icon-only"></ion-icon>
      </ion-button>
    </ion-buttons>
    <ion-title>...</ion-title>    
  </ion-toolbar>
</ion-header>

I suggest another alternative

Create a new class (CustomNavController) that extends from NavController

import { Optional } from '@angular/core';
import { UrlTree, Router } from '@angular/router';
import { Location } from '@angular/common';
import { NavController, Platform } from '@ionic/angular';
import { NavigationOptions } from '@ionic/angular/dist/providers/nav-controller';

export class CustomNavController extends NavController {
  constructor(
    platform: Platform,
    private _location: Location,
    @Optional() private _router?: Router,
  ) {
    super(platform, _location, _router);
  }

  navigateBack(url: string | UrlTree | any[], options: NavigationOptions = {}): Promise<boolean> {
    this.setDirection('back', options.animated, options.animationDirection);
    return new Promise((resolve, reject) => {
      this._location.back();
      resolve();
    });
  }
}

Add the CustomNavController class as your NavController to your providers (main module)

{ provide: NavController, useClass: CustomNavController }

Example:

@NgModule({
    ...
  providers: [
    ...
    { provide: NavController, useClass: CustomNavController }
    ...
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

This is absolutely required to be fixed. Right now I have to add custom ion-button to handle all the back navigation as a temporary workaround.

I am experiencing the same issue as well. 🙂

It likewise happens with the { skipLocationChange: true } setting where the browser back button honors it while the ion-back-button does not.

Hi there,

This issue has been resolved by #17879. I have pushed a nightly build of Ionic, and it would be great if someone could test and provide some feedback. (npm i @ionic/core@dev @ionic/angular@dev)

We appreciate your patience as we worked to fix this issue!

@paulstelzer any news on this? This is critical to a good UX and my team is waiting to launch the app.

Any update on this?

In my case on login page after successful login, I redirect user to dashboard:

this.router.navigateByUrl('/dashboard', { replaceUrl: true });

I assume that pressing hardware back button from dashboard, shouldn’t take the user to the Login page since I am passing replaceUrl: true. But it doesn’t work and pressing back button takes back to login page.

I am also experiencing this same issue. In doing further investigation, I believe the issue is that when doing a router.navigate with replaceUrl: true, it is not updating the url / fullPath within the StackController of the ion router outlet.

In my scenario my page has child routing, and on enter it sets a default child route programatically. So for example navigating to /home will automatically do a relative navigation to /home/child using replaceUrl: true. Now from here if I navigate to /another-page the back button takes me to /home instead of /home/child which is very similar to the op’s issue.

Is there any way I can force the stack in ion router outlet to update the url of the current view?

Hi @naveedahmed1,

This is a known issue. You can follow the Back Button Issue Thread for more info.

Thanks!

@KevinKelchen,

Ah yes thank you for the reminder! Would you be able to create an issue for it? I think it’s worth tracking that separately.

Thanks!

I’ve tried it out for myself and replaceUrl seems to be working! 🙂

At the same time, as I mentioned in my comment above, { skipLocationChange: true } similarly doesn’t work with the ion-back-button.

I thought it was similar enough of an issue that fixing replaceUrl may have also fixed skipLocationChange but that didn’t end up being the case. Therefore, perhaps it should be considered a separate issue.

Should we expect a permanent fix from Ionic team anytime soon?

@manucorporat @paulstelzer I think reliable and robust routing should have higher priority.

The way I’ve overcome this issue:

  1. Created a custom directive:
import {Directive, HostListener} from '@angular/core';
import {Location} from '@angular/common';

@Directive({
  selector: '[app-location-back]'
})
export class LocationBackDirective {
  constructor(private location: Location) { }

  @HostListener('click', ['$event'])
  clickEvent(event) {
    event.preventDefault();
    event.stopPropagation();
    this.location.back();
  }
}
  1. Used the directive’s selector as a property on my ion-button:
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-button app-location-back fill="clear">
         <ion-icon name="arrow-back" slot="icon-only"></ion-icon>
      </ion-button>
    </ion-buttons>
    <ion-title>...</ion-title>    
  </ion-toolbar>
</ion-header>

Nice ! I would add this.navCtlr.setDirection('back'); to the directive in order to properly animate it also 😃

@naveedahmed1 we are also experiencing this similar issue too! Even worse, we are actually using the root navigation direction when navigating to our home page after the login page, which should reset the navigation stack, but the hardware back button still takes the user to the login page, looks like replaceUrl also does not fix that problem.

I have had some success by migrating to the Angular router (not too hard coming from the new NavController that lightly wraps the Angular router and looking at the NavController’s methods in order to know what Angular router calls to replace them with). I’ve also created a custom Angular back button component that just uses Angular’s Location.back() when you click it. That’s how I’m getting around this issue for now.

Any updates on this issue from the Ionic team? Thanks!