nativescript-angular icon indicating copy to clipboard operation
nativescript-angular copied to clipboard

Android - Back navigation breaks with nested page-router-outlets.

Open sbknick opened this issue 5 years ago • 10 comments

Environment Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

  • CLI: 5.3.0
  • Android Runtime: 5.1.0
  • NativeScript-Angular: 7.1.0
  • Angular: 7.1.0

Describe the bug On Android, navigation history is broken when navigating backward via nested page-router-outlets. Note: This works as expected on iOS just fine.

To Reproduce

  1. Create a NS Angular project with routes like so...
{ path: "", redirectTo: "/home/(homeoutlet:lounge)", pathMatch: "full" },
{ path: "home", component: HomeComponent, children: [
    { path: "lounge", component: LoungeComponent, outlet: "homeoutlet" },
    { path: "garage", component: GarageComponent, outlet: "homeoutlet" }
] },
{ path: "work", component: WorkComponent }
  1. On the Lounge page, add a button to navigate to "/home/(homeoutlet:garage)"
  2. On the Garage page, add buttons to navigate "routerExtensions.back()" and to "/work".
  3. On the Work page, add a button to navigate "routerExtendsion.back()".
  4. Run the app.
  5. Starting at Home/Lounge, navigate to Home/Garage then to Work. Then go back() and attempt to go back() again.
  6. The page will remain on the Home/Garage page despite that not being the start of the nav stack.

Expected behavior If I navigate from home/lounge -> home/garage -> work, then i press back() twice, I should return to home/lounge.

Sample project https://github.com/sbknick/ns-android-nested-back-nav

Additional context On iOS, this functions as expected.

sbknick avatar Apr 08 '19 14:04 sbknick

HI @sbknick, Thank you for the provided sample project. I was able to recreate the issue on my side and I will log it as a bug, which we will investigate further. As a temporary solution. You can replace the router-outlet with page-router-outlet.

tsonevn avatar Apr 09 '19 11:04 tsonevn

Ahh, my apologies, I meant to commit <page-router-outlet> not <router-outlet>, the bug occurs using either. The same when using .back() and .backToPreviousPage() for either.

sbknick avatar Apr 09 '19 12:04 sbknick

I have a similar issue and the router.navigate Promise resolves on the second try with the value null. Maybe that's a bit of extra information.

redmagic avatar Apr 17 '19 16:04 redmagic

I'm having exactly the same issue, are there possible workarounds?

adobrasinovic avatar Aug 22 '19 12:08 adobrasinovic

I'm also struggling with this issue. any solution for this issue?

farismohammed avatar Sep 28 '19 03:09 farismohammed

I am also running into this issue. Guess there's been no progress?

Eonfuzz avatar Oct 07 '19 03:10 Eonfuzz

I found a kind of workaround, by forcing the back event on homeoutlet, when the back button leads to one of children page of HomeComponent.

Considering than /home/(homeoutlet:lounge) is the starting page, I simply added in ngOnInit method in HomeComponent :

application.android.off(application.AndroidApplication.activityBackPressedEvent);
application.android.on(application.AndroidApplication.activityBackPressedEvent, (args : application.AndroidActivityBackPressedEventData) => {
       if(this.routerExtensions.router.url.indexOf("/home/(homeoutlet:") != -1 && this.routerExtensions.router.url.indexOf("/home/(homeoutlet:lounge") == -1) {
            args.cancel = true;
            this.routerExtensions.back({ relativeTo: this.activeRoute, outlets: ['homeoutlet'] });
       }
})

That was enough for me to have the behaviour expected

Impact on this workaround: if you use a modal page in one of a children page of HomeComponent, then the back button will not close the modal

GrEg00z avatar Nov 03 '19 15:11 GrEg00z

@sbknick

The behavior you observe is expected. Calling routerExtensions.back(); or routerExtensions.backToPreviousPage(); navigates back on the last navigated outlet.

When you navigate from lounge to garage, you navigate inside the homeoutlet, back at this point means going back in the homeoutlet, so you can successfully go back to lounge.

When you navigate to work, this is effectively navigation from home to work which happens inside the primary outlet, back at this point means going back in the primary outlet to home (which remembered its state so the homeoutlet is still on garage). Going back again is an attempt to navigate back in the primary outlet which is not possible as there is no route before home. In order to perform the navigation inside the homeoutlet, you can call routerExtensions.back({ relativeTo: this.route; });, where route is the ActivatedRoute service injected through the component’s constructor:

export class GarageComponent {
    constructor(
        private route: ActivatedRoute,
        private routerExtensions: RouterExtensions
    ) {
        console.log("garage loaded");
    }

    goBack() {
        // Don't navigate to previous page:
        // this.routerExtensions.backToPreviousPage();
        // Navigate relative to the activated route instead:
        this.routerExtensions.back({ relativeTo: this.route });
    }
    goToWork() {
        this.routerExtensions.navigate(["work"]);
    }
}

Nested navigation is thoroughly explained in this excellent article by Alexander Djenkov.

tgpetrov avatar Nov 08 '19 16:11 tgpetrov

Hi Team ,

Any fix available for this issue?

itsmerockingagain avatar Apr 28 '21 13:04 itsmerockingagain

So basically it is not possible to have a tab navigation with pages which are not part of the tab system without hacks. I think this should be better communicated in the documentation.

Is there any plan for a better support for back navigation between different outlets?

tujlaky avatar May 11 '21 11:05 tujlaky