WebCake

Recently I added a login workflow to my Ionic 2 app, where the user has to log in before they can take any other action. If the user is already logged in when they open the app, they’re automatically redirected to the main view. In this case, the main view is the TabsPage layout.

This turned out to be a great opportunity to explore how Nav worked, and how NavController accesses its various stacks. In the interest of sharing, all of my findings are documented here. It should be noted that I use the words ‘stack’ and ‘array’ interchangeably.

This write-up is based on release 2.0.0-beta.11. Be aware that development and documentation are constantly changing, and so the syntax in this post might not be accurate once Ionic 2 is out of Beta.

Nav Stacks

If you’ve used Nav or NavController at all, you might find that it’s a bit odd getting started. From what I’ve found, the following pseudo-object literal maps how each Nav maintains control of its views in the TabsPage layout. Note this is just a model, not an attempt at an accurate rendition. Happy to take suggestions on how to improve if it’s not clear.

{
    App<Nav>: [
         TabsPage<Nav>: [
            [
                tab1Root,
                tab1Inner,
                tab1DeepInner,
                tab1SuperInner
            ]
        ]
    ]
}

So based on this model, we can start to see how nested controllers subscribe to a hierarchy. Each page can create its own copy of NavController, which will give it access to the various Nav scopes in a navigational tree. The App has its own Nav, which a NavController in TabsPage can access. However the TabsPage has its own Nav, which the pages in the TabsPage stack can immediately access via their respective copies of NavController.

Each array of pages has its own root, which we can access via various root-based method:

import { NavController } from `ionic-angular`;
import { tab1SuperInner } from './tab1SuperInner'
import { newTab } from `../otherTabs/newTab`;

export class tab2DeepInner {
    // creates a local copy of NavController
    constructor(private _nav: NavController) {}

    public goBack() {
        // navigates to the previous page in the stack,
        // which based on the model above is tab1Inner
        this._nav.pop();
    }

    public goToSuper() {
        // determines whatever page will be next in the stack;
        // and although we're matching the pattern above, it could
        // be any page that we want
        this._nav.push(tab1SuperInner);
    }

    public backToRoot() {
        // navigates back to the root of the stack,
        // which based on the model above is tab1Root
        this._nav.popToRoot();
    }

    public reviseRoot() {
        // changes the root to a different item in the stack
        // or a different stack entirely!
        this._nav.setRoot(newTab);
    }
}

From within the scope of the TabsPage stack, we’d operate within the range of the four tab1... pages. So regardless of where we are in that stack, calling the backToRoot() method would bring us back to tab1Root. Similarly, revising the root of the stack will set whatever page we pass in as the first item in the array. This is what TabsPage stack would look like after you’ve called reviseRoot():

{
    App<Nav>: [
        TabsPage<Nav>: [
            newTab
        ]
    ]
]

This revises the root – and therefore the stack – of the current Nav stack/array. In doing so, we can introduce the user to a completely new set of views, which would be helpful in a situation where the user would need to log in before they can view certain pages.

TabsPage routing explained

The TabsPage only displays one active stack at a time. On load, the TabsPage will load whatever Page is set as the root of first Tab. You can set those root properties in app/pages/tabs/tabs.ts:

// from the diet app I'm currently working on

import { Component } from '@angular/core';
import { CurrentDay } from '../current-day/current-day';
import { History } from '../history/history';
import { Page3 } from '../page3/page3';
import { Settings } from '../settings/settings';

@Component({
  templateUrl: 'build/pages/tabs/tabs.html'
})
export class TabsPage {

  tab1Root: any;
  tab2Root: any;
  tab3Root: any;
  tab4Root: any;

  constructor() {
    this.tab1Root = CurrentDay;
    this.tab2Root = History;
    this.tab3Root = Page3;
    this.tab4Root = Settings; 
  }
}

Those are converted to template values in the template at app/pages/tabs/tabs.html:

<ion-tabs>
  <ion-tab [root]="tab1Root" tabTitle="Today" tabIcon="pulse"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="Tab 2" tabIcon="chatbubbles"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="Tab 3" tabIcon="cog"></ion-tab>
  <ion-tab [root]="tab4Root" tabTitle="Settings" tabIcon="cog"></ion-tab>
</ion-tabs>

When a user clicks on the items in the TabsPage bottom nav, the root page of the active Nav stack becomes the corresponding tabXRoot property, as set above. For example, the current stack might look like the following, indicating that the user is currently on tab1DeepInner:

{
    App<Nav>: [
        {
            TabsPage<Nav>: [
                tab1Root,
                tab1Inner,
                tab1DeepInner
            ]
        }
    ]
}

Once the user clicks on the second tab, the stack would then become the following:

{
    App<Nav>: [
        {
            TabsPage<Nav>: [
                tab2Root
            ]
        }
    ]
}

Notice that within the scope of the TabsPage stack, references to the root of the stack are limited to the confines of the pages in the local array. Once we want to get into injecting a page in front of the TabsPage component in the global App stack, we get into working with the Nav hierarchy.

Nav Hierarchy

Working within the Nav hierarchy reminds me of working within the $scope hierarchy in Angular 1.x. NavControllers are limited to their own array, so you have to know which NavController you need to target in order to take certain actions in the heirarchy. Let’s take a look.

App stack root page

My application needed a login screen to open up before the Tabs layout. So in order to do this, I had to change the root page of the App stack:

// app/app.ts

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { LoginPage } from './pages/login/login';

@Component({
    template: '<ion-nav [root]="rootPage"></ion-nav>',
})
export class MyApp {
    private rootPage:any;

    constructor(platform: Platform) {
        this.rootPage = LoginPage; // Oh...it's you.
        platform.ready().then(() => {});
    }
}

By setting a new page in the mix, we’ve changed how the app loads. Instead of navigating directly to the TabsPage screen, it’ll load to the LoginPage. At this point, the Nav model looks something like this:

{
    App<Nav>: [
        LoginPage
    ]
}

Not much going on there. Once we have an authenticated user, we can redirect them to the TabsPage layout. Since we’re still in the App stack, the LoginPage can refer directly to its own array scope.

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { AuthService } from '../auth/auth.service'; 
import { TabsPage } from '../tabs/tabs';

@Component({
    templateUrl: 'build/pages/login/login.html',
    // note, this is the olden way and still works as of Angular RC 4, used in Ionic Beta 11, 
    // but will eventually be replaced with the NgModel approach introduced in RC 5
    providers: [AuthService] 
})
export class LoginPage {
    constructor(private _nav: NavController, private _auth: AuthService) {}

    login() {
        this._auth.login(username, password).then(user => {
            // do something with the user,
            // and redirect to the TabsPage
            this._nav.push(TabsPage, {}, {animate: false});
        }).catch(err => {
            console.log(err);
        });
    }
}

This will add the TabsPage and its child stack to the App’s navigation array. The LoginPage will still live at the root of the App nav stack, but the entirety of the tab hierarchy will be displayed in front of it, giving the authenticated user access to the tab-based content. The model would look like so:

{
    App<Nav>: [
        LoginPage,
        TabsPage<Nav>: [...]
    ]
}

Note that I chose not to animate the transition to the TabsPage. That’s a personal UX consideration, as I didn’t want the user to get the impression that they could easily transition back to the login screen. Instead I wanted that to appear as an intermediary between app load and the tab-based content.

Parent and child stacks

For me, trouble came when I tried to log out.

export class LogoutComponent {
    constructor(private _auth: AuthService, private _nav: NavController) {}

    logout() {
        this._auth.logout();
        this._nav.setRoot(LoginPage);
    }
}

This logout component lived in the header for every page within the TabsPage stacks, in a Component. That being the case, it was part of the pages in the child stack, not part of the App stack.

From within a page in the TabsPage stacks – that is, from within tab1Inner, for example – trying to navigate back to the LoginPage had some terrible results when I would log out, and then log back in. Do that a couple times and you get this monstrosity:

Screen Shot 2016-03-17 at 7.16.25 AM

The reason was that I was trying to revise the root of the current stack, not the parent stack. In doing so, I was constantly resetting the root of the TabsPage stack to LoginPage, and then back to TabsPage. The following model explains the monstrosity above:

{
    App<Nav>: [
        LoginPage,
        TabsPage<Nav>: [
            LoginPage,
            TabsPage<Nav>: [
                LoginPage,
                TabsPage<Nav>: [
                    tab1Root,
                    tab1Inner,
                    tab1DeepInner,
                    tab1SuperInner
                ]
            ]
        ]
    ]
}

That’s bad, mm’kay? Instead we want to remove the entire hierarchy on logout so that the only page in the App stack is the LoginPage.

In order to do this, we have to access the root of the App’s nav stack. This will give us access to the current stack’s parent. So if I’m operating in the page tab1DeepInner, I would call the following to drop everything in the app nav stack and get back to the original state, which only had the LoginPage in the stack:

import { Component } from '@angular/core';
// Notice I'm not importing NavController
// Instead I'm importing App, which gives me access to
// app-level properties, such as the root NavController
import { App } from 'ionic-angular';

import { AuthService } from '../../auth/auth.service'; 
import { LoginPage } from '../../pages/login/login';

@Component({
    templateUrl: 'build/components/logout/logout.html',
    providers: [AuthService] 
})
export class LogoutComponent {
    constructor(private _app: App, private _auth: AuthService) {}

    logout() {
        this._auth.logout();

        // Now I'll access the root NavController for the app,
        // and use that to reset the nav stack

        const root = this._app.getRootNav();
        root.popToRoot();

        // since I only have two items in the root NavController,
        // I could also have run root.pop() instead
    }
}

The getRootNav() method returns the root NavController of the App, which I can use to navigate away from the TabsPage stack and back to the original page, thus giving me the result I’m looking for:

{
    App<Nav>: [
        LoginPage
    ]
}

Logging in again then revises the App stack so that its displayed page is the TabsPage, and the LoginPage is no longer the most recent item in the stack.

Conclusion

With a better understanding of how the TabsPage navigation works, I’m personally much more comfortable with using the NavController, as well as working in and around the TabsPage and its children.

In another post, I’ll talk about how I built the login screen, from start to finish.

28 responses to “Exploring Nav Hierarchy in the Ionic 2 Tabs Page”

  1. chaw says:

    Thanks so much for the solution!
    I came to the same problem as you’ve explained in the “Parent and child stacks” section.

    Understanding how parent & child stacks work in ionic 2 new navigation feature does help a lot during development process.

    Thank you!

  2. Thanks!

    I was wondering how to “pop out of the tabs”, but this explained it nicely πŸ™‚

  3. Brian says:

    Good stuff! I’d love to see how you’re checking for authentication and bypassing the initial LoginPage when the user is logged in. I’ve been having trouble in beta.4 with nav not updating the UI after checking Storage for auth values.

    • Colin says:

      In my LoginPage, I have this method set using the onPageWillEnter hooK:

      onPageWillEnter() {
          const auth: AuthModel = this._user.getUser();
          if(auth) {
              this._nav.setRoot(TabsPage);
          } else {
              this.ready();
          }
      }
      

      The UserService getUser() method (this._user.getUser()) simply calls to Firebase to check the current authorized user:

      public getUser() {
          return this._data.db.getAuth();
      }
      

      There is a bug where even after the user auth token expires, the getAuth() method returns an active user. I think it’s because Firebase stores a user auth token in localStorage, and that’s where the method refers to. It’s actually what’s prevented me so far from posting about my LoginPage πŸ™‚ . Once I have that ironed out (which should be this weekend since I want to get it to users on Sunday), I’ll write about my login workflow.

  4. Tom says:

    Really helpful! Thanks for sharing. Using this.nav.rootNav.popToRoot() seems like a great way to escape the tabs as part of a logout operation. (tested with Ionic 2 Beta 10)

    • EM Products says:

      maybe I’m new to ionic 2 but I can’t seem to find rootNav in this.nav of the child ? to use this.nav.rootNav.popToRoot() in the tabs , I’m making all the nav public in the constructor

      • Colin says:

        I just tried it out with the latest Beta of Ionic, Beta 11. When I tried the code listed above, I got a TS compilation error about the rootNav property not existing on the NavController class. However, when I log out NavController in the console, the rootNav property is definitely there. So I did some digging in the source: https://github.com/driftyco/ionic/blob/master/src/navigation/nav-controller-base.ts#L942

        It turns out there’s a new way that the folks building Ionic want you to grab the root. I haven’t tried it yet, but I’ll give it a shot in the morning.

        You can still hack the deprecated way if you want, by going around the TS compiler:

        this.nav['rootNav'].popToRoot()
        

        That’ll access the private method in the compiled JS. However that’s definitely not a long term solution, just something to get you unblocked. If I can get the new app.getRootNav() working tomorrow morning I should be able to put up a revision to this post on Thursday or Friday morning.

      • Colin says:

        Post has been updated to use the app.getRootNav() approach. Let me know if you have any more problems.

        • EM Products says:

          thanks Colin for your quick replay
          I did solve it by pushing the tabs page and get back to welcome by

          var t: Tabs = navCtrl.parent;
          t.parent.setRoot(WelcomePage, {}, { animate: true, direction: ‘back’ });

          did you faced this kind of problem before ??

          https://github.com/driftyco/ionic/issues/5484

          • Colin says:

            I actually haven’t. There have been times when I haven’t been able to execute actions on the first try, which makes me think that the events I’m firing aren’t getting picked up by change detection. That might just be the Angular 1 digest-cycle hangover talking.

          • EM Products says:

            thanks for your reply, I did manage to get over this bug by change the push command to setRoot command.

  5. Ante Burazer says:

    Great article, it helped me a lot in understanding Ionic 2 Tabs.
    I have the following situation and would need a litle help.

    Two tabs shows two lists. The first list is the list of contacts and when user clicks on particular item it leads him to contact details.
    User can add contacts to favorites, which is another list displayed in second tab.

    When user goes to contact details from tab 1, then switches to tab 2 and gets back to tab 1 contact details will still be shown because every tab has it’s own stack and remembers top page in the stack.
    I want to pop to root every time when I change tab (to show a list and not contact details) and I’m wondering where to implement that logic.

    I tried in TabsPage on tab change event and it works but after that I have problems with change detections. When I’m changing parameters of the class it’s not reflecting changes in the view.

    @ViewChild(‘tabs’) tabRef: Tabs;
    tabChanged(event) {
    event.pop({animate: false});
    }

    Thanks

    • Colin says:

      That’s a good question. I’d have to play with it a bit to figure out how I would do it. If you can wait a few days I should be able to put together a working demo. Out of curiosity, what problems are you having with change detection?

      • Ante Burazer says:

        I can wait, of course.

        Problem:

        I have a list of favorites which can be reordered by using Ionic 2 list reorder property. I also want to enable/disable reorder by clicking on a button. It looks like this:

        <ion-list [reorder]="reorderEnabled" (ionItemReorder)="reorderItems($event)">

        [reorder] property defines if list is enabled or disabled and I’m changing it with “reorderEnabled” variable which is a private variable (boolean) of my class.
        I have a “toggle reorder” button used for toggle “reorderEnabled” variable. When I come from tab 1 to tab 2 and click “toggle reorder” button (and “tabChanged” event is implemented – from previous post) nothing happens. So I have to go to favorite item details page, get back to favorites list and “toggle reorder” button starts working normally.

        When I turn off “tabChanged” event everything works fine.

        It looks like I have to wake up Angular to start performing change detection. I’m doing that by changing pages in the current stack.
        I’m not sure if it’s related to Angular or Ionic. I will try to implement “reorder button” click event as an Observable but it still bothers me why it doesn’t work with this implementation.

        Thanks for your help

        • Colin says:

          I’ve experienced what you’re talking about in terms of change detection failing, but it was in an earlier Beta of Ionic 2 – I think it was Beta 4. If you’re not on the latest, try updating. As for the functionality you’re talking about, I pushed up a project to my GitHub that covers the basics of what you’re looking for. It contains a tab that refreshes its history whenever a user navigates to it, and another that contains default behavior. Let me know if this helps. If not I’m happy to keep exploring this with you. It’s given me some thoughts on a new post that would make a nice follow-up to this one.

  6. Al says:

    Hello, for trying to explain this but I am still lost πŸ™‚
    I would like to ignore all user clicks on the tabs so that on a phone device the “back button” exits instead of cycling backwards thru the tabs.

    I tried adding this method

    public goBack() {
    // navigates to the previous page in the stack,
    // which based on the model above is tab1Inner
    this.NavController.popToRoot();
    }
    to all my 4 tabs page .ts files but they don’t seem to trigger on the Android.
    How can I simulate and debug the “back button” on a browser/windows? is it via the “backspace” key?

    is goBack() an override of some method? or should I be subscribing the “back button” event/callback or tab clicks and how? in order to issue this.NavController.popToRoot()

    Thank you.

    • Colin says:

      If I’m understanding correctly, you’re trying to trigger functionality that brings the user back to the first page in a Tab nav hierarchy when the user clicks the Tab. Is that correct?

  7. Al says:

    Hi Colin, I do not want my application to remember the history of (1) user clicks on the tabs or (2) tabs selection from code by means of .select(). BTW I am using this.navController.parent.select( index ) to display tab2 from a selection on tab1, and tab3 from a selection on tab2 and tab4 from a selection on tab3 (I have list a 4 hierarchical pick lists)

    Using the .select() does NOT display any back arrows πŸ™‚ so having the hardware back button navigate back in the sequence the tabs may have been clicked during a session is a nuisance. If the user entered the main screen of tabs and clicked a bunch of tabs then pressed the hardware back button, he would expect the app to exit.

    Of course if I have navigated explicitly with .push() especially to a totally new page other than the main 4 tabs, then I would expect the displayed back arrow (on nav bar) as well as the hardware back button (android / windows) to do the same and return backyards in the history of obvious navigation.

    I hope this is clear, let me know πŸ™‚ Thank you.

    • Colin says:

      Sorry, I misunderstood what you’re asking. I’m pretty sure I catch what you’re saying now. I’ve never used the select() method in the Tabs component, so I can’t speak too much to that guy. But I just pushed up a demo project that might give an example that does what you’re looking for. In that project, one of the tabs in the navigation always resets its history on activation. You could probably apply it to all tabs if that’s what you’re looking for.

      • Ante Burazer says:

        Thank you very much for your effort and contribution. Github project works great and solves the problem entirely.
        The only thing I want to point out is that all pages, in stack you want to reset, need to have inluded NavController:

        `import {NavController} from ‘ionic-angular’;

        constructor(public nav: NavController) {}`

        in order to access nav property in tabs.ts file
        Maybe it could be unclear for people who are starting with Ionic and are not so familiar with Ionic Tabs.

        Thanks again for great article.

  8. Al says:

    Hi Colin, thanks for posting the code. However, I can only wild guess as to what showRoot() is attempting to do. You seem to obtain a reference to the “band” tab then somehow retrieve an array of ViewController with
    let views = this.tabRef[‘_views’];
    which ionic link describes this API ‘_views’ ?
    Does views here mean the number of times this tab “bands” has been visited (/clicked)?

    Code semantics aside, I ran your code both on an Android device and an emulated Galaxy S6 API 23 on GenyMotion emulator.
    In both cases I could not see any different behaviors between the “bands” and “movies” tab. I mean I visit the bands tab make a selection eg. nirvana, I get thrown in a page, the back arrow displays I have to back out obviously. The same experience is exhibited with the ‘movies’ tab. I do not see any “resetting” you mention about the “bands” tab children views. If you are testing with iOS, perhaps your experience with iOS devices is different perhaps your tabs remain in view at all times. This may explain why I could not follow your “test” steps as I have to back out when making a selection in either of the tabs. (Perhaps the backing out was trivial and you just left it out of your test steps.

    Regarding the “hardware back button” I think there is no point of you trying to test it (experience it) on iOS, as the notion of a “back button” simple does not exist in the Apple realm :).

    Regarding my quest, currently ionic tracks every single tab click and tab activation via .select() into a “navigation history” not visually obvious to the user and causes the hardware back button on Android to back step to each and every visits to the tabs. I think this is ridiculous or a bug. The HW back button is meant to back out and up a hierarchy traversal by the user, but not a lateral (siblings) navigation.
    Image I visit a product website I select Specs tab then decide that’s not for me, so I go over the Overview tab and drill down inside of it. Now when I back out, I hope the site would not force thru every siblings/children from lateral traversals I may have done. Rather I should be able to back out always up and exit/close if that later notion exists.

    I put the following code together in app.ts and call it from the constructor platform.ready().then(() => { … } but it seems to render the hardware back button dead=does nothing (I am not able to debug on the device or emulator, I don’t know how. And I can’t debug this concept on desktop browser as I don’t know if there is a keystroke equivalent to a hardware back button, I tried Control-Backspace :).

    // https://forum.ionicframework.com/t/android-hardware-back-button-in-ionic-2/44522/13
    // 20160806
    HandleHardwareBackButton() {
    //
    this.platform.registerBackButtonAction(function (event) {
    let nav = this.app.getComponent(‘nav’);
    if (nav.canGoBack()) {
    nav.popToRoot();
    // nav.pop();
    }
    else {
    this.confirmExitApp(nav);
    }
    }, 101);
    }

    On a side note if you decide to make any modification to your code, I suggest using something like Tab1 = US and Tab2 = Europe, the next level would be states for US and countries for Europe, and a 3rd level would selecting popular cities with those. The navigation would be easier to follow and trap issues if any I hope by most readers. Bands and Movies requires a specific audience.

    Finally, and off subject, I find it ridiculous that a bare example has 20,000 to 30,000 under node_modules, it is a bit overkill, has anyone considered npm install tiny-binary-packages-of-some-sort πŸ™‚ It made me think twice before doing a git clone on your sample πŸ™‚

    Thank you for taking the time trying to help me out. I am new to ionic2 JS and TS, coming from C#, SIlverlight, WPF, Xamarin frameworks it a bit hard digest all of these notions and tools. Hybrid approach seems promising but I already see lots of issues, just like the others πŸ™‚

    • Colin says:

      Hey, sorry it took me a few days to get back to you. This gives me a much better idea of what you’re looking for. Yes, the implementation I had was for iOS. And maybe it’s because I had just wrapped it up, or because I was half-focused on the Olympics while I was building it, but that was something I put together for the previous commenter and thought you had the same problem. It’ll probably take me the weekend to think this one through if you don’t mind waiting a little longer or haven’t found a solution yet. Similarly, good call on the mock data. At work we generally use grunge bands to demo various data models, so it’s a weird habit. But you’re entirely right – the blog has a bigger audience. I’ll update over the weekend as well. In answer to your question about the _views property, it’s an array of the amount of different pages that have been loaded into the navigation stack on top of the root page. Re: node_modules… I got nothing there. Something I just accepted as a thing a while ago. Last, no worries on being new to this stuff. We’re all learning.

    • Colin says:

      Ok homey-san, I’ve updated the project to incorporate the Android back button with (I’m pretty sure) the functionality you’re looking for. I used the registerBackButton method listed in the platform docs. If you look in app/tabs/tabs.ts you’ll find I added some functionality to the constructor() (although it probably should have gone in a lifecycle hook):

      this.platform.registerBackButtonAction(() => {
        let child: Tab = this.tabs.getSelected();
        if(child['_views'].length > 1) {
          child.pop();
        } else {
          navigator['app'].exitApp();
        }
      });
      

      That should take care of Android. As for the browser back button, I wouldn’t know where to begin on that. In my humble opinion, I probably wouldn’t put an Ionic app in the web. I’d try to keep Ionic-based functionality and components as encapsulated as possible, so that most of the components in my app could be pulled out into a sister pure Angular 2 project. The reason I say that is that the navigation structure fits more inline with a touch interface based on simplified view context, and in a browser I’d personally want to see a more robust navigation system, with a component distribution that’s built for a larger form-factor. That’s just my opinion though. Sorry I can’t be more help on that one.

      • Al Gantori says:

        Hi, thanks for the update, and taking the time to put all together. Somehow I was not notified but I ran into your entry in the ionic forum.

        Anyhow, I like it when I just use cut and paste πŸ™‚ and it works

        // 20160815
        // handles the hardware back button behavior on the Android
        // https://webcake.co/exploring-nav-hierarchy-in-the-ionic-2-tabs-page/#div-comment-148
        // https://github.com/colinjlacy/ionic-2-smart-tabs/blob/master/app/pages/tabs/tabs.ts
        this.platform.registerBackButtonAction(() => {
        let child: Tab = this.Tabs.getSelected();
        if (child['_views'].length > 1) {
        child.pop();
        } else {
        navigator['app'].exitApp();
        }
        });

        I did adjust the casing as I dislike camel-case and anything case sensitive πŸ™‚

        Perhaps you have an idea on solving my other issue and perhaps doing a post
        https://forum.ionicframework.com/t/how-to-hide-and-show-individual-tabs-programmatically/60562 (really how to keep a page alive for a whole session, like one containing a youtube player or a slideshow and which would benefit from a single time setup).

        Thanks a bunch!

  9. Joan says:

    When I met the problem like that, I changed the service method for getting the user login state from a Promise to a wrapper over an Observer, and then subscribe to it in app.ts (app.component.ts now!)

    Then every time a user’s action causes his or her login state changes, the app would just call something that fetches the latest login state and update the observer.

Leave a Reply