Nativescript-angular: Clearing tabview page-router-outlets is not working

Created on 30 Aug 2018  路  8Comments  路  Source: NativeScript/nativescript-angular

Since nested page-router-outlets are not yet supported (see https://github.com/NativeScript/nativescript-angular/issues/1351), our application consists of a login in a modal and a tabview with multiple page-router-outlets. After a user is logged in, the login modal disappears and the individual pages are loaded in the tab-view. This works as expected.

In one of the tab-view pages we have a logout button that should unload all the pages in the tab-view and re-open the login modal. Our approach is to use an outlet navigation to null-pages, like so:
this.router.navigate([{ outlets: { firstTab null, secondTab: null } }], { relativeTo: this.activatedRoute.parent });
(I found this solution in https://github.com/angular/angular/issues/5122 and I've also tried all other suggested approaches)

Unfortunately this doesn't work in our application.

Since we've already altered our approach using a login page in a modal instead of nested-routing, we have to find a solution to unload the pages in the tab-view. This issue, combined with issue 1351 puts us into a deadlock..

Any suggestions?

Which platform(s) does your issue occur on?

  • Both iOS and Android on emulator and devices

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

  • CLI: 4.2.2
  • Cross-platform modules: 4.2.0
  • Runtime(s): 4.2.0
  • Plugin(s): (see playground example)

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

Is there any code involved?

Playground: https://play.nativescript.org/?template=play-ng&id=8eLtNS&v=10

Open the playground example.
Click on 'Perform successful login' to mimic a login >> Logout >> Click on 'Perform successful login' again. (Login functionality can be found in modal/login.component.ts. Logout functionality can be found in home/home.component.ts)

As you can see, the contents of the tab-view are not unloaded, and a duplicate home and browse page is loaded.

tab-view

Most helpful comment

@MartoYankov Thanks for your update. We've been following your updates closely and have implemented the above scenario as soon as nested PRO's where available.
The blog post gives a nice overview of the changes and new possibilities with nested PRO's!

All 8 comments

@FBorgonjen Thanks for reporting this scenario.

Firstly, regarding unloading of components via navigating to null instances, I don't think this can work reliably in {N}. This is a forward navigation in a page-router-outlet and {N} implements a custom route reuse strategy that keeps components in the history alive. This is necessary to manage and mimic the native mobile navigations happening in the background. Also as you have observed, modal views don't destroy the views that presented them. This is just how the mobile platforms work. My suggestion would be to not rely on component lifecycle to handle sensitive information disposal. Instead, use a service that holds, presents and disposes the data. Would that be possible in your scenario? I have an example in a playground below.

I also investigated the issue you reported with your playground and identified it as a possible bug not connected to routing. I logged a separate issue with a stripped down version of your playground - https://github.com/NativeScript/nativescript-angular/issues/1503. As I mention in the issue, there is a workaround if you have one navigation inside the modal view. Here is an example for you in another playground - https://play.nativescript.org/?template=play-ng&id=XfRwGm&v=4. I also implemented a login service that holds the sensitive login time data. This data is then directly bound to the home page view, so that when we logout we unset it and the data is cleared from the view. Check it out and let me know if this is what you need.

Further, there are a couple of problems in the playground example that you sent, that I thought are worth pointing out:

  1. In the app.module the ModalDialogService is already declared as provider in NativeScriptModule, so you don't need to declare it explicitly.
  2. The LoginComponent shouldn't be declared in the app routing config if you are going to open it as a modal view. Modal views themselves are not navigations, but they can be containers for a different level of navigation. In the playground I sent you there is a login modal root (containing a page-router-outlet), which is the modal view and a login component which is navigated inside the modal view. In this case the login component should be declared in the app routing config.

@MartoYankov, thanks for your elaborate reply and playground example. I understand that components should be kept alive, especially when showing modals. We have several services that manage sensitive user information, so that is also taken care of. But what your playground example doesn't show and is the essential question: how to reset all windows in the tab-views to their original state after a logout + re-login.

In our app we have 5 tabs and in each of the tabs we can navigate to other pages and/or change a component state. After a logout these navigation and component states should be reset. So with the knowledge that we cannot unload the views in the tabs, how could we achieve that?

Here is an updated playground: https://play.nativescript.org/?template=play-ng&id=8eLtNS&v=14
Please perform the following steps to reproduce the scenario:

  • Login
  • Go to the 'Browse' tab and select an item
  • Go to the 'Home' tab and logout
  • Re-Login and watch what happens to the views

@FBorgonjen I wanted to demonstrate that the router navigation/reset was not the cause of the glitchy view navigations after modal view close. That is why I omitted them in the playground reproduction.

The navigation with clearHistory should be the correct way to reset all tabs. The updated playground example doesn't contain the workaround for https://github.com/NativeScript/nativescript-angular/issues/1503, which is to make one navigation to a page inside the modal view. Doing this should fix the glitchy navigations that happen after modal close.

I updated my playground with the browse master-detail page and the reset using clearHistory to test the steps to reproduce with the workaround - https://play.nativescript.org/?template=play-ng&id=XfRwGm&v=5. On iOS this works fine. After logout->login there is no Back button on the home tab and going back to the browse page is showing the master list page as expected. Can you confirm this is what you observe on your end?

On Android there appears to be a bad glitch going back to the browse page in which you see the detail page for a second before the navigation to the master-list kicks in. Can you confirm this too?

The Android glitch is clearly a bug. I will look into it and figure out if there is a good workaround for it. Thanks again for reporting this.

Hi @MartoYankov, thanks again for your reply and playground example. We actually had quite a similar approach in our app, but ours has more glitchy issues than the example you've sent. I've updated our code using your playground example. But since we have routes that are restricted with guards, we are not able to navigate to the tabs when logged-out. Also our routing is slightly different since we do not navigate within the outlets on startup. That's why our approach differs from the playground example.

I've updated the playground so that the (timing of) navigation resembles our approach (guards are not necessary for this example). Now you can see the problems we run into. https://play.nativescript.org/?template=play-ng&id=XfRwGm&v=7 Do you have any suggestion on how we could overcome these problems?

Hi @FBorgonjen I see the problems and it seems you will need the nested page router outlets feature to implement it the way you want it. In a way you are trying to emulate a login page that on login navigates to the tabs page. The approach with login as a modal requires (for the history to work properly) to have an underlying view component that is loaded. Otherwise, the native navigations and the angular navigations mismatch.

What I mean is that you need a scenario where the underlying native part can do "Login Page" -> "Nav Tabs Page", while the modal login one is actually "Nav Tabs Page" -> "Login Modal with Nav Tabs Page behind" -> "Nav Tabs Page". We are actively working on making the first scenario possible. In the meantime, can you share if there are any blockers that won't let you implement the login as a modal in your application? Basically, all your initial TabView components should be able to init without data, populate the data on login and clear it on logout.

@FBorgonjen Nesting page-router-outlets is now supported and the original scenario you wanted to implement should be possible now. You can check out the blog post about it - https://www.nativescript.org/blog/implementing-a-login-for-nativescript-apps-with-tab-based-navigation.

@MartoYankov Thanks for your update. We've been following your updates closely and have implemented the above scenario as soon as nested PRO's where available.
The blog post gives a nice overview of the changes and new possibilities with nested PRO's!

Tabs.Compoent.ts

import { RouterExtensions } from "nativescript-angular/router";
ngOnInit() {

    this.routerExtension.navigate([
        {
            outlets: {
                yourfeed: ["yourfeed"],
                globalfeed: ["globalfeed"],
                featuremore: ["featuremore"]
            }
        }
    ], { relativeTo: this.activeRoute });

}

FeatureMore.Component.Ts

onLogout() {
this.routerExtension.navigate(["../login"], { clearHistory: true });
}

Was this page helpful?
0 / 5 - 0 ratings