Wrong navigation direction/animation with Angular router after CanDeactivate stops navigation
Bug Report
Ionic version: [x] 4.x
Current behavior:
Using the Angular router to forward navigate after a CanDeactivate route guard has stopped a NavController.back from taking place results in the wrong navigation animation direction and a reset Ionic push/pop stack.
Expected behavior:
The correct navigation animation will be used and the Ionic stack will not be reset when forward navigating with the Angular router even in the case where a CanDeactivate route guard has stopped a back navigation.
Steps to reproduce:
- Clone the following repo: https://github.com/KevinKelchen/issue-ionic4-can-deactivate-animation
- It is the Angular sidemenu starter template with minor modifications (namely that the sidemenu items, when clicked, do different things).
- Run
npm i. - Run
ionic serve. - Open Google Chrome Dev Tools.
- In Google Chrome Dev Tools click "Toggle device toolbar" to simulate a device UI.
- In device toolbar settings, from the device type dropdown choose "iPad Pro."
- This will make it use the
iosmode whose navigation animation directions are more obvious to the eye (content moving left or right). - "iPad Pro" is a large enough resolution that the sidemenu will remain visible on the screen.
- This will make it use the
- In device toolbar settings, from the zoom level dropdown choose "100%."
- Sometimes with a smaller percentage the click areas get messed up.
- Reload the browser to ensure that the simulated user agent will be used.
- In the Dev Tools Elements panel, expand the nodes for the following path:
body > app-root > ion-app > ion-split-pane > ion-router-outlet- This will allow you to keep a visual on the Ionic push/pop stack as you navigate in the app.
- Click
List (Router.navigate)and note that the navigation direction/animation goes forward as it is usingRouter.navigate.- You'll also see the Page get added to the Ionic stack in the Elements panel.
- Click
Bonus (Router.navigate)and note that the navigation direction/animation goes forward as it is usingRouter.navigate.- You'll also see the Page get added to the Ionic stack in the Elements panel.
- Click
Home (NavController.back)and note that the navigation direction/animation goes back as it is usingNavController.back.- Since this used
NavController.back, you will be back on theListscreen. You'll see theBonusPage was removed from the Ionic stack in the Elements panel.
- Since this used
- In the Dev Tools Console, copy/paste the following statement and hit Enter/return:
window.disableNav = true- This flag will force the
CanDeactivateAngular route guard to returnfalseand prevent subsequent navigations.
- Click
Home (NavController.back). The navigation will be prevented by theCanDeactivateroute guard. - In the Dev Tools Console, copy/paste the following statement and hit Enter/return:
window.disableNav = false
- Click
Bonus (Router.navigate)and note that the navigation direction/animation goes backwards instead of forwards like it's supposed to.- You'll also see all of the Pages in the Ionic stack in the Elements panel have been destroyed except for the current Page you're on (
Bonus).
- You'll also see all of the Pages in the Ionic stack in the Elements panel have been destroyed except for the current Page you're on (
Related code:
See Steps to reproduce.
Other information: Here's what I can tell about what's happening:
- In the
NavController, on theNavigationStartAngular router eventthis.guessDirectionandthis.guessAnimationare set. These values are used inNavController.consumeTransitionwhenthis.directionisauto, or in other words, is not explicitly set to a specific direction.- Note that it is also in
consumeTransitionthatthis.directionis set back to the default value ofauto.
- Note that it is also in
NavController.backwill explicitly set the direction/animation usingsetDirection.- When the
CanDeactivateguard returnsfalseand stops the navigation, thebackdirection/animation fromsetDirectiondo not get reverted to the default values but remain in place. This is becauseconsumeTransitionnever happens which is where they would otherwise get reset to the default values. - Then upon forward navigating with the Angular router, in
consumeTransition,this.directionstill has a non-autovalue ofbackand it uses that instead ofauto/this.guessDirection/this.guessAnimation.
Perhaps after every navigation--even if it doesn't succeed--these default values can be reset. Not sure if it'd involve subscribing to certain Angular router events or if there's a better/existing "hook" to put this type of handling within the Ionic framework.
I’ve worked around the issue for now by explicitly calling setDirection with forward navigation values before invoking the Angular router to forward navigate. Using NavController.navigateForward is another option.
Ionic info:
Ionic:
ionic (Ionic CLI) : 4.6.0 (/usr/local/lib/node_modules/ionic)
Ionic Framework : @ionic/angular 4.0.1
@angular-devkit/build-angular : 0.12.4
@angular-devkit/schematics : 7.2.4
@angular/cli : 7.2.4
@ionic/angular-toolkit : 1.4.0
System:
NodeJS : v10.13.0 (/usr/local/bin/node)
npm : 6.4.1
OS : macOS Mojave