ionic-framework icon indicating copy to clipboard operation
ionic-framework copied to clipboard

Wrong navigation direction/animation with Angular router after CanDeactivate stops navigation

Open KevinKelchen opened this issue 6 years ago • 0 comments

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:

  1. 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).
  2. Run npm i.
  3. Run ionic serve.
  4. Open Google Chrome Dev Tools.
  5. In Google Chrome Dev Tools click "Toggle device toolbar" to simulate a device UI.
  6. In device toolbar settings, from the device type dropdown choose "iPad Pro."
    • This will make it use the ios mode 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.
  7. In device toolbar settings, from the zoom level dropdown choose "100%."
    • Sometimes with a smaller percentage the click areas get messed up.
  8. Reload the browser to ensure that the simulated user agent will be used.
  9. 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.
  10. Click List (Router.navigate) and note that the navigation direction/animation goes forward as it is using Router.navigate.
    • You'll also see the Page get added to the Ionic stack in the Elements panel.
  11. Click Bonus (Router.navigate) and note that the navigation direction/animation goes forward as it is using Router.navigate.
    • You'll also see the Page get added to the Ionic stack in the Elements panel.
  12. Click Home (NavController.back) and note that the navigation direction/animation goes back as it is using NavController.back.
    • Since this used NavController.back, you will be back on the List screen. You'll see the Bonus Page was removed from the Ionic stack in the Elements panel.
  13. In the Dev Tools Console, copy/paste the following statement and hit Enter/return:
    • window.disableNav = true
    • This flag will force the CanDeactivate Angular route guard to return false and prevent subsequent navigations.
  14. Click Home (NavController.back). The navigation will be prevented by the CanDeactivate route guard.
  15. In the Dev Tools Console, copy/paste the following statement and hit Enter/return:
    • window.disableNav = false
  16. 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).

Related code:

See Steps to reproduce.

Other information: Here's what I can tell about what's happening:

  1. In the NavController, on the NavigationStart Angular router event this.guessDirection and this.guessAnimation are set. These values are used in NavController.consumeTransition when this.direction is auto, or in other words, is not explicitly set to a specific direction.
  2. NavController.back will explicitly set the direction/animation using setDirection.
  3. When the CanDeactivate guard returns false and stops the navigation, the back direction/animation from setDirection do not get reverted to the default values but remain in place. This is because consumeTransition never happens which is where they would otherwise get reset to the default values.
  4. Then upon forward navigating with the Angular router, in consumeTransition, this.direction still has a non-auto value of back and it uses that instead of auto/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

KevinKelchen avatar Feb 20 '19 02:02 KevinKelchen