Nativescript: Routing breaks when using Frame.goBack(to: BackstackEntry)

Created on 21 Mar 2017  路  16Comments  路  Source: NativeScript/NativeScript

Tell us about the problem

Lets say we have an app that consists of 4 pages, and lets name these pages page1, page2, page3 and page4. And lets say that we have navigated from page1 to page4, visiting page2 and page3 along the way.

Now, I wish to go back to page2 using Frame.goBack(to: BackstackEntry) by looking up page2 this way frameModule.topmost().backStack[1]. Then if I try to navigate to page3 nothing will happen. Navigating back to page1 works, but navigating forward still doesn't work.

If, instead of navigating to page2, I navigate to page1 or page3, routing will not break.

Which platform(s) does your issue occur on?

Both

Please provide the following version numbers that your issue occurs with:

  • CLI: 2.5.0
  • Cross-platform modules: 2.5.2
  • Runtime(s): iOS and Android: 2.5.0

Please tell us how to recreate the issue in as much detail as possible.

I have created a sample app that reproduces this issue: https://github.com/abinici/ns-goback-issue

Most helpful comment

Hi @tsonevn,

I tried your suggestion, when navigating from page2 to page3, but then my back navigation button disappears on page3, which prevents the user from navigating back to page2.

What I am trying to accomplish, is that the pages that the user navigates to, such as page2, page3 and page4, should all be put on the stack so that user is not prevented from navigating back from page4 to page3 and page2.

But when hitting a button on page4, I would like the user to be taken back to page2 without having to visit page3.

The function I am looking for is something like popToRoot in Ionic2: http://ionicframework.com/docs/v2/api/navigation/NavController/#popToRoot

You use setRoot() to set a root for the current navigation stack. And when calling popToRoot() you go back multiple levels in your page hierarchy.

Currently, I am forced to use Frame.goBack(to: BackstackEntry) and then I have to call pop() x times in this.routerExtensions.locationStrategy, to keep things in sync (I have added a pop-method to NSLocationStrategy). Obviously, this is an ugly hack, but I dont know the implementation well enough to make things the pretty way.

Maybe you could give me some directions so that I or someone else could implement this functionality in a PR, with something like back(steps: int) or back(url: string)?

All 16 comments

Hi @abinici,
Thank you for your interest in NativeScript.

This is something expected when using FrameModules in this way in NativeScirpt Angular 2 project.

Using frameModule for navigation is a concept used in NativeScirpt core project. Regarding this module, the purpose of goBack() method is to give you simple way to navigate to the previous page. In case you would like to make navigation in a pure NativeScirpt project, you should use navigate(<page_name>) method, where you should specify the page name.

In your case, when you are using NativeScript Angular 2 template, there is another way to making navigation. First of all to in this type of project you should use angular Router module or RouterExtensions, which extends the angular one. For example:

Navigate to another page.

import { Component, OnInit } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import {RouterExtensions} from "nativescript-angular/router"

import frameModule = require("ui/frame");

@Component({
    moduleId: module.id,
    selector: "page4",
    templateUrl: "./page4.component.html",
})
export class Page4Component implements OnInit {
    constructor(
        private route: ActivatedRoute,
        private router: Router, 
        private routerExt:RouterExtensions
    ) {}

    ngOnInit(): void {

    }

    goback() {
        this.router.navigate(["page2"]);
    }
}

Navigate to the previous page.

import { Component, OnInit } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import {RouterExtensions} from "nativescript-angular/router"

import frameModule = require("ui/frame");

@Component({
    moduleId: module.id,
    selector: "page4",
    templateUrl: "./page4.component.html",
})
export class Page4Component implements OnInit {
    constructor(
        private route: ActivatedRoute,
        private router: Router, 
        private routerExt:RouterExtensions
    ) {}

    ngOnInit(): void {

    }

    goback() {

        this.routerExt.back();
    }
}

For further info, you could also review the documentation.

Hi @tsonevn,

I understand that the routing in Navigation Core and Angular is different. But Nativescript Angular is missing the functionality I needed. Thats why I began using Framemodule, because it had the method goBack(to: BackstackEntry), which I was hoping could solve my problem.

And to elaborate this, I dont want to go to previous page. I wish to go 2 or more pages back in history. So, when I navigate from page4 to page2, I want the pages page4 and page3 removed from the stack, in one single action. How can this be accomplished with Nativescript Angular?

I am guessing that the only way resolve this with Nativescript Angular is by calling routerExt.back() multiple times, but this is not optimal.

I think methods like these would help a lot: routerExt.goBack(url: string) or routerExt.goBack(steps: int)

Hi @abinici,
You could still use NativeScirpt RouterExtensions module and its navigate method in combination with clearHistory option, which will allow you to disable saving the page to the back stack history.
For example:

login() {
    // app logic here ...
    this.routerExtensions.navigate(["/main"], { clearHistory: true });
}

For more info review the documentation.

Hope this helps.

Hi @tsonevn,

I tried your suggestion, when navigating from page2 to page3, but then my back navigation button disappears on page3, which prevents the user from navigating back to page2.

What I am trying to accomplish, is that the pages that the user navigates to, such as page2, page3 and page4, should all be put on the stack so that user is not prevented from navigating back from page4 to page3 and page2.

But when hitting a button on page4, I would like the user to be taken back to page2 without having to visit page3.

The function I am looking for is something like popToRoot in Ionic2: http://ionicframework.com/docs/v2/api/navigation/NavController/#popToRoot

You use setRoot() to set a root for the current navigation stack. And when calling popToRoot() you go back multiple levels in your page hierarchy.

Currently, I am forced to use Frame.goBack(to: BackstackEntry) and then I have to call pop() x times in this.routerExtensions.locationStrategy, to keep things in sync (I have added a pop-method to NSLocationStrategy). Obviously, this is an ugly hack, but I dont know the implementation well enough to make things the pretty way.

Maybe you could give me some directions so that I or someone else could implement this functionality in a PR, with something like back(steps: int) or back(url: string)?

Maybe this issue should be moved to https://github.com/NativeScript/nativescript-angular?

Hi @abinici,
Indeed this is a valid feature - an ability to navigates back to the specific page.
While building the router navigation in NativeScript Angular 2 project, we have not thought about supporting this feature.
Regarding that, I will change the label of the issue to Feature request and we will research, what is the best way to implement this functionality for NativeScript Angular 2.

In the meantime, you could call goBack() method to navigate back to the needed page as you have suggested in your previous comment.

You could also keep track on the issue for further.

Need same feature like @abinici :)

This feature would make so much sense if added. I had to use a workaround when I needed a similar feature. Using the navigationFrom and checking for BackButton navigation to route to the desired page. Angular's implementation of skipLocationChange would have simply done the much-needed trick.

Is there any indication when this feature will be available? We would also really like to use it instead of using tricks with the clear history and self made back buttons or other hacks to get it to work as intended

+1

+1

@abinici how is you pop method looks like? I want to solve the issue with the same workaround. But actually I have no Idea how to solve it, first i was thinking to just pop the state array, but it is not working pretty well :D

One solution to extend the NSLocationSrategy without change the file itself could be that:

(<any>NSLocationStrategy.prototype).pop = function() {
            // YOUR CODE TO POP 
        };

(<any>this._router.locationStrategy).pop();

This issue was moved to NativeScript/nativescript-angular#1367

@ThunderAnimal, its been a while ago since I've used NativeScript, but have you tried calling callPopState after popping?

(<any>NSLocationStrategy.prototype).pop = function() {
    state = states.pop();
    this.callPopState(state, true);
};

Because when I look at the source for NSLocationStrategy.back() they seem to call callPopState whenever they do a page navigation:

https://github.com/NativeScript/nativescript-angular/blob/master/nativescript-angular/router/ns-location-strategy.ts

@tsonevn actually this is a valid issue in {N} and not only nativescript-angular
I want to do the same, i tried using clearHistory. Now the issue is that it moves back to the selected page but it loses the page state.
I think the issue is that if the root page is already the one we are navigating to, {N} recreates the page instead of just closing all other in front.
so if you do:

  • start in page1
  • change the state of page1
  • go to page2
  • go to page3
  • go to page1 using clearHistory
    => you go back to page1 but it recreates it and you loose the page 1 state

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fmmsilva picture fmmsilva  路  3Comments

NickIliev picture NickIliev  路  3Comments

tsonevn picture tsonevn  路  3Comments

dhanalakshmitawwa picture dhanalakshmitawwa  路  3Comments

OscarLopezArnaiz picture OscarLopezArnaiz  路  3Comments