Mahmoud Ismail
Mahmoud Ismail

Reputation: 1617

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

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.

tabs.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;
  }
}

tabs.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?

Upvotes: 4

Views: 6684

Answers (5)

Jeremy Belolo
Jeremy Belolo

Reputation: 4539

Nowadays :

IonicModule.forRoot(MyApp, {
  tabsHideOnSubPages: true
})

Upvotes: 0

Francisco Neto
Francisco Neto

Reputation: 347

As I answered in the ionic forum: 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>

2) 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
  }

}

Upvotes: 0

JanP
JanP

Reputation: 1581

Create a tabs array in your component and use this to dynamically load your template. You can then easily manipulate the tabs array in your component:

tabs.ts

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

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

  tabs: any[] = [
    { title: "Home", root: Page2, icon: "home" },
    { title: "tab_title", root: NotificationsPage, icon: "notifications" },
    { title: "tab_title", root: MessagesPage, icon: "home" },
    { title: "tab_title", root: InstructionsPage, icon: "home" },
    { title: "tab_title", root: ExpertsPage, icon: "home" }
  ];

  constructor(public userData: UserData) {
    // get variable from local storage
    this.userData.getUser().then((value) => {
      if(value.typeLabel == 'Expert') {
        this.tabs[0].root = Page1;
        console.log('1->',value.typeLabel);
      } else if(value.typeLabel == 'Client'){
        this.tabs[0].root = Page2;
        console.log('2->',value.typeLabel);
      }
    });
  }
}

tabs.html

<ion-tabs>
  <ion-tab *ngFor="let tab of tabs" [root]="tab.root" [tabTitle]="tab.title" [tabIcon]="tab.icon"></ion-tab>
</ion-tabs>

Upvotes: 3

Mohan Gopi
Mohan Gopi

Reputation: 7724

try using *ngIf

<ion-tabs *ngIf = "variable">
  <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>

Inside your .ts file

make variable variable = true to display the tabs make itfalse not to display the tabs.

Upvotes: 3

misha130
misha130

Reputation: 5706

Instead of setting a variable value to the tab1Root set it to be a function so its executed everytime the variable is reached.

this.tab1Root = () => this.variable?Page1:Page2;

Upvotes: 0

Related Questions