How to manage dynamic menu item?


#1

Hello All,

Thanks in advance.

I have created demo application and make the login module. I have defined global variable in service provider after successfully login true value will be set in global variable and based on that variable i have set condition for menu in app.html but menu condition is not working. So please share your feedback for the same.

App.component.ts

this.loginState = brokerUser.loginState; /* True or false value assigned based on login */

this.accountMenuItems = [
            {title: 'My Account', component: MyAccountPage, icon: 'ios-contact'},
            {title: 'Logout', component: WelcomePage, icon: 'log-out'},
        ];

        this.loginMenuItems = [
            {title: 'Login', component: LoginPage, icon: 'ios-contact'}
        ];

App.html

<ion-list *ngIf="loginState == true">
      <ion-list-header>
        Account
      </ion-list-header>
      <button menuClose ion-item *ngFor="let menuItem of accountMenuItems" (click)="openPage(menuItem)">
        <ion-icon item-left [name]="menuItem.icon"></ion-icon>
        {{menuItem.title}}
      </button>
    </ion-list>

    <ion-list *ngIf="loginState == false">
      <ion-list-header>
        Account
      </ion-list-header>
      <button menuClose ion-item *ngFor="let menuItem of loginMenuItems" (click)="openPage(menuItem)" >
        <ion-icon item-left [name]="menuItem.icon"></ion-icon>
        {{menuItem.title}}
      </button>
    </ion-list>

#2

Please share enough code to enable somebody to copy/paste everything into a scratch project and replicate your environment.


#3

App.component.ts

import {Component, ViewChild} from '@angular/core';
import {Nav, Platform} from 'ionic-angular';
import {StatusBar} from '@ionic-native/status-bar';
import {SplashScreen} from '@ionic-native/splash-screen';

import {PropertyListPage} from '../pages/property-list/property-list';
import {BrokerListPage} from '../pages/broker-list/broker-list';
import {FavoriteListPage} from '../pages/favorite-list/favorite-list';
import {WelcomePage} from '../pages/welcome/welcome';
import {AboutPage} from '../pages/about/about';
import {MyAccountPage} from '../pages/my-account/my-account';
import {LoginPage} from '../pages/login/login';

import {BrokerService} from "../providers/broker-service-rest";

export interface MenuItem {
    title: string;
    component: any;
    icon: string;
}

@Component({
    templateUrl: 'app.html'
})
export class MyApp {
    @ViewChild(Nav) nav: Nav;

    rootPage: any = WelcomePage;

    appMenuItems: Array<MenuItem>;

    accountMenuItems: Array<MenuItem>;

    loginMenuItems: Array<MenuItem>;

    helpMenuItems: Array<MenuItem>;

    loginState:boolean;

    constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen, public brokerUser:BrokerService) {
        this.initializeApp();

        this.appMenuItems = [
            {title: 'Properties', component: PropertyListPage, icon: 'home'},
            {title: 'Brokers', component: BrokerListPage, icon: 'people'},
            {title: 'Favorites', component: FavoriteListPage, icon: 'star'},
            {title: 'Get Preapproved', component: WelcomePage, icon: 'checkmark-circle'},
        ];

        this.loginState = brokerUser.loginState;

        this.accountMenuItems = [
            {title: 'My Account', component: MyAccountPage, icon: 'ios-contact'},
            {title: 'Logout', component: WelcomePage, icon: 'log-out'},
        ];

        this.loginMenuItems = [
            {title: 'Login', component: LoginPage, icon: 'ios-contact'}
        ];

        this.helpMenuItems = [
            {title: 'Welcome', component: WelcomePage, icon: 'bookmark'},
            {title: 'About', component: AboutPage, icon: 'information-circle'},
        ];

    }

    initializeApp() {
        this.platform.ready().then(() => {
            // Okay, so the platform is ready and our plugins are available.
            // Here you can do any higher level native things you might need.
            this.statusBar.styleLightContent();
            this.splashScreen.hide();
        });
    }

    openPage(page) {
        // Reset the content nav to have just this page
        // we wouldn't want the back button to show in this scenario
        this.nav.setRoot(page.component);
    }
}

app.ts

<ion-menu [content]="content">

  <ion-content>

    <img src="assets/img/dreamhouse-logo.svg" class="menu-logo"/>

    <ion-list>
      <ion-list-header>
        Shop
      </ion-list-header>
      <button menuClose ion-item *ngFor="let menuItem of appMenuItems" (click)="openPage(menuItem)">
        <ion-icon item-left [name]="menuItem.icon"></ion-icon>
        {{menuItem.title}}
      </button>
    </ion-list>

    <ion-list>
      <ion-list-header>
        Help
      </ion-list-header>
      <button menuClose ion-item *ngFor="let menuItem of helpMenuItems" (click)="openPage(menuItem)">
        <ion-icon item-left [name]="menuItem.icon"></ion-icon>
        {{menuItem.title}}
      </button>
    </ion-list>

    /* Need show this menu after login */
    <ion-list >
      <ion-list-header>
        Account
      </ion-list-header>
      <button menuClose ion-item *ngFor="let menuItem of accountMenuItems" (click)="openPage(menuItem)">
        <ion-icon item-left [name]="menuItem.icon"></ion-icon>
        {{menuItem.title}}
      </button>
    </ion-list>

    /* Need show this menu without login */
     <ion-list >
      <ion-list-header>
        Account
      </ion-list-header>
      <button menuClose ion-item *ngFor="let menuItem of loginMenuItems" (click)="openPage(menuItem)" >
        <ion-icon item-left [name]="menuItem.icon"></ion-icon>
        {{menuItem.title}}
      </button>
    </ion-list>

  </ion-content>

</ion-menu>

<!-- Disable swipe-to-go-back because it's poor UX to combine STGB with side menus -->
<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>

login.ts

import {Component} from '@angular/core';
import {NavController, NavParams/*, ToastController*/} from 'ionic-angular';
import {BrokerService} from '../../providers/broker-service-rest';
import {MyAccountPage} from '../my-account/my-account';

@Component({
    selector: 'page-broker-detail',
    templateUrl: 'login.html',
    providers:[BrokerService]
})
export class LoginPage {

    LoginDetails = {email:'', password:''};
    broker: any;

    constructor(public navCtrl: NavController, public navParams: NavParams, public service: BrokerService/*, public toastCtrl: ToastController*/) {
        this.broker = this.navParams.data;
        service.findById(1).then(
            broker => this.broker = broker
        );
    }

    loginSubmit() {
        var me = this;
        this.service.login(this.LoginDetails.email,this.LoginDetails.password)
            .then(function(response) {
                var data = response.json();

                if(data.status) {
                    me.service.loginState = true;
                    console.log('First');
                    me.navCtrl.push(MyAccountPage);
                }
            });
        ;
    }
}


#4

Eliminate the [providers] of LoginPage. Its presence is making LoginPage have a different instance of BrokerService than MyApp does, which is causing your problem.


#5

Thanks, It’s working now :slight_smile: