How I can hide and show tabs conditionally - Ionic 2?


#1

The case is the following: I have a ion-tabs container with several ion-tab elements, and different users that logs into my application. What I need to do is to show or hide the ion-tab elements depending on the user type logged.

The problem is that I need to do this dynamically, and if I use a directive like [show]="variable", it does not work.

tab.ts

import { Component } from '@angular/core';

import { Page1 } from '../page1/page1';
import { Page2 } from '../page2/page2';

@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage {
  // this tells the tabs component which Pages
  // should be each tab's root Page
  tab1Root: any;
  tab2Root: any;
  tab3Root: any;
  tab4Root: any;
  tab5Root: any;
  variable: any;

  constructor(public userData: UserData) {
   // get variable from local storage
    this.userData.getUser().then((value) => {
      if(value.typeLabel == 'Expert') {
        this.variable = true;
        console.log('1->',value.typeLabel);
      }else if(value.typeLabel == 'Client'){
        this.variable = false;
        console.log('2->',value.typeLabel);
      }
    });

    this.tab1Root = this.variable?Page1:Page2; <-- i want to show specify tabs depending on variable value
    this.tab2Root = NotificationsPage;
    this.tab3Root = MessagesPage;
    this.tab4Root = InstructionsPage;
    this.tab5Root = ExpertsPage;
  }
}

tab.html

<ion-tabs>
  <ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="tab_title" tabIcon="notifications"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="tab_title" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab4Root" tabTitle="tab_title" tabIcon="home"></ion-tab>
  <ion-tab [root]="tab5Root" tabTitle="tab_title" tabIcon="home"></ion-tab>
</ion-tabs>

But always this.tab1Root return Page1;

What am I doing wrong? Can somebody help me?


#2

the logic you provide is seems wrong?

you assign the page before you get the value from userdata,

for better understanding print a console log
below the

this.tab1Root = this.variable?Page1:Page2;

you will understand how the code works


#3

Hello everybody,

I have the same problem with ionic 2.I would like dynamically hide or show tabs which are depend on the input of the user. How can I do this?

Thanks for your answers.


#5

It just won’t work. That’s how Ionic is built, it currently does not allow for dynamically setting the tab root page. I had to hack around for some hours and finally got it to work in the following way:

  1. Get the reference of the tabs component and the reference of the tab you want to set dynamically. Do not set the [root] attribute for this dynamical tab because Ionic will run a method that simply won’t allow you to update the root page for this tab later.
<ion-tabs #appTabs>
  <ion-tab #tabA tabTitle="Tab A" tabIcon="list-box"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="Tab B" tabIcon="albums"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="Tab C" tabIcon="pulse"></ion-tab>
  <ion-tab [root]="tab4Root" tabTitle="Tab D" tabIcon="more"></ion-tab>
</ion-tabs>
  1. In the TabsPage file:
import { Component, ViewChild } from '@angular/core';
import { Store } from '@ngrx/store'; // I'm using ngrx
import { Tabs, Tab } from 'ionic-angular';
import { Observable } from 'rxjs/Observable';
import 'rxjs/operator/filter';
import 'rxjs/operator/map';

import { TabA1Page } from '...';
import { TabA2Page } from '...';
import { TabBPage } from '...';
import { TabCPage } from '...';
import { TabDPage } from '...';
import { AppState } from '../../app.reducer';
import { DashboardCard } from '...';

@Component({
  templateUrl: 'tabs.page.html',
  selector: 'page-tabs'
})
export class TabsPage {
  public tab1Root: any; // As you can see, it's not set yet.
  public tab2Root: any = TabBPage;
  public tab3Root: any = TabCPage;
  public tab4Root: any = TabDPage;

  // Get the references
  @ViewChild('appTabs') private tabsRef: Tabs;
  @ViewChild('tabA') private tabRef: Tab;

  constructor(private store: Store<AppState>) {}

  public ionViewDidEnter() {
    // These three sources can change the root page for the tab A:
    const defaultDashboard$ = this.store.select('task', 'fetchDashboardCards', 'value');
    const dashboardByProject$ = this.store.select('task', 'fetchDashboardCardsByProject', 'value');
    const dashboardByDueDate$ = this.store.select('task', 'fetchDashboardCardsByDueDate', 'value');

    Observable
      .merge(defaultDashboard$, dashboardByProject$, dashboardByDueDate$)
      .filter(v => v != null)
      .map((dashboard: DashboardCard[]) => dashboard[0].layout === 'project' ? TabA1 : TabA2)
      .distinctUntilChanged()
      .subscribe(this.setTabARootPage.bind(this));
  }

  private setTabARootPage(rootPage) {
    // This is the hack

    // set the root property that we didn't set in the view as [root]="..."
    this.tabRef.root = rootPage;

    /*
    * Modifying private attributes to make it work.
    * This will allow Ionic to run the "tabsInstance.load()" method to load a new root page
    * It also allows us to select the same tab again.
    */
    this.tabRef._loaded = false;
    this.tabsRef._tabs[0].isSelected = false;
 
    this.tabsRef.select(this.tabRef); // select the tab again
  }

}

This worked for me. Please adapt it to your case and let me know the result :wink: