Skip to content

When using nested router-outlet, the back button exits the App #477

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
m-abs opened this issue Sep 28, 2016 · 10 comments
Closed

When using nested router-outlet, the back button exits the App #477

m-abs opened this issue Sep 28, 2016 · 10 comments

Comments

@m-abs
Copy link
Contributor

m-abs commented Sep 28, 2016

I'm trying to add child-routes to my Angular Native App, but when I click my android back-button the App just exits.

I've tried to write an example to show what the problem it here: https://github.com/m-abs/angular2-seed-advanced/tree/child-router
It's based on Nathan Walker's angular2-seed-advanced as that's what we use in our project.

What I've done:

What happens:

  • I tap on the Button nsRouterLinks and the components are loaded. Even the ActionBar works per ChildComponent, which were a bit of a surprise.
  • Click on the devices back-button, exits my App right away.

What I'd expect:

  • I tap on the Button nsRouterLinks and the components are loaded
  • I click back and the go back to the previous component in history

More data:
I've tried tracing it to try and make heads or tail on it:

JS: ns-router: NSLocationStrategy.path(): /
JS: Router Event: NavigationStart(id: 1, url: '/')
JS: Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
JS: Router Event: RoutesRecognized(id: 1, url: '/', urlAfterRedirects: '/home/child1', state: Route(url:'', path:'') { Route(url:'home', path:'home') { Route(url:'child1', path:'child1') }  } )
JS: ns-router: NSLocationStrategy.path(): /
JS: ns-router: NSLocationStrategy.replaceState pushing new state: null, title: , url: /home/child1, queryParams: null
JS: ns-router: PageRouterOutlet.activate() inital page - just load component
JS: Router Event: NavigationEnd(id: 1, url: '/', urlAfterRedirects: '/home/child1')
JS: NativeLifecycle: fragment0[0]<Page(1)>.onCreateAnimator(0, enter, undefined): null
JS: ns-router: nsRouterLink.tapped: /home/child2 usePageRoute: true clearHistory: undefined transition: true
JS: ns-router: NSLocationStrategy._setNavigationOptions({"clearHistory":false,"animated":true})
JS: Router Event: NavigationStart(id: 2, url: '/home/child2')
JS: Router Event: RoutesRecognized(id: 2, url: '/home/child2', urlAfterRedirects: '/home/child2', state: Route(url:'', path:'') { Route(url:'home', path:'home') { Route(url:'child2', path:'child2') }  } )
JS: ns-router: NSLocationStrategy.path(): /home/child1
JS: ns-router: NSLocationStrategy.pushState state: null, title: , url: /home/child2, queryParams: null
JS: Router Event: NavigationEnd(id: 2, url: '/home/child2', urlAfterRedirects: '/home/child2')
JS: NativeLifecycle: NativeScriptActivity.onBackPressed;
JS: TNS Application - Suspended
JS: NativeLifecycle: NativeScriptActivity.onStop();
JS: NativeLifecycle: fragment0[0]<Page(1)>.onDestroyView()
JS: NativeLifecycle: HIDDEN fragment0[0]<Page(1)>; destroyed: true
JS: NativeLifecycle: fragment0[0]<Page(1)>.onDestroy()
JS: TNS Application - EXIT
JS: NativeLifecycle: NativeScriptActivity.onDestroy();

As you can see NSLocationStrategy.pushState(/home/child2) is called for the child-route, but after onBackPressed the App just exits.

@m-abs m-abs changed the title nested router-outlet, back button exits app. When using nested router-outlet, the back button exits the App Sep 28, 2016
@m-abs
Copy link
Contributor Author

m-abs commented Sep 29, 2016

Minor update:

If I add an listener for backButtonPressed on android and call routerext.back() myself iit works as expected.
The action bar for the child routes won't have an back-btn, but I can live with that.
See here: https://github.com/m-abs/angular2-seed-advanced/blob/child-router-android-back-button/nativescript/app/pages/app/app.component.ts#L58-L69

But should this kind of workaround really be needed?

@vakrilov
Copy link
Contributor

You pretty much answered yourself. In Android the back button is bound to the page navigation, which i s controlled by the . So when you tap back - you should go to the previous page (skipping all intermediate router-outlet navigations).

The solution you found is a valid one, although _getStates() directly seem like a hack. I've done a PR(#481) that exposes a canGoBack() method the should make you code cleaner.

@vakrilov vakrilov assigned vakrilov and unassigned vakrilov Sep 30, 2016
@vakrilov
Copy link
Contributor

vakrilov commented Oct 3, 2016

Closing this issue for now - please reopen if needed.

@vakrilov vakrilov closed this as completed Oct 3, 2016
@SBD580
Copy link

SBD580 commented Jan 22, 2017

@vakrilov what about nested page-router-outlet? I had expected that the back button will be acting on the inner page-router-outlet but instead it acting on the outer one. Is this as expected?

@vakrilov
Copy link
Contributor

Yes, the reason for that is consistency between IOS and Android. In IOS the <Back button will take you to the previous page, so we do the same in Android.
You can change the behavior by handling activityBackPressed and doing routerExtensions.back().

@SBD580
Copy link

SBD580 commented Jan 23, 2017

I see. I thought page-router-outlet define pages, so going back to previous page should act on the inner one and only then on the outer (when no more routes left)

@sittingbool
Copy link

sittingbool commented Jul 9, 2017

The whole Navigation structure is a mess in my opinion. Its the wrong way around and i always struggle a lot if i want to combine navigation controls like i am used to with ios. In iOS and many Android Apps nowadays you have a tab view and navigate the content of each tab. otherwise tabs make no sense. On a website you would navigate inside the tab too by pressing back. in nativescript the tabview is constructed to be inside the "UINavigationController". A back button should not change anything on the tabview but navigate its content backwards. To have an page-router-outlet that cant be wrapped into someting is a brake of that structure. Usually i want a tabview outside, sometimes also a side-drawer. and definitively i dont want it an each page but globally.

@vipul1905
Copy link

I tried to use this function routerExtensions.back() on activityBackPressedEvent but I get error "cannot get property back". I have imported the RouterExtensions file as well. Could anyone help me out with this? Thanks.

@vakrilov
Copy link
Contributor

Hey @vipul1905: Can you please make sure you are using the NativeScriptRouterModule in your application and that you are injecting the the RouterExtensions inside your component using the angular DI.

@sittingbool
Copy link

I certainly did. I used the template project where this was set already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants