0

enter image description here

I am using a Ionic Side-Menu application. The above image highlights my issue. I would like the menu active state to be changed when I navigate to that particular page. The menu state works fine when clicking the menu item to navigate and not anywhere else to navigate.

On clicking "Go To List" from Home, I am using the following code in my HomePage.

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { ListPage } from '../list/list';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  listPage =  ListPage; 
  constructor(public navCtrl: NavController) {

  }

  goToList(){
    this.navCtrl.setRoot(this.listPage);
  }
}

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 { HomePage } from '../pages/home/home';
import { ListPage } from '../pages/list/list';
import { GalleryPage } from '../pages/gallery/gallery';

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

  rootPage: any = HomePage;
  activePage: any;

  pages: Array<{title: string, component: any}>;

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

    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Home', component: HomePage },
      { title: 'List', component: ListPage },
      { title: 'Gallery', component: GalleryPage}
    ];

    this.activePage = this.pages[0];

  }

  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.styleDefault();
      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);
    this.activePage = page;
  }

  checkActive(page){
    return page === this.activePage;
  }
}

Any help on this?

nijin
  • 556
  • 2
  • 16
  • Could you also add the corresponding HTML? Or even better create a [stackblitz](https://stackblitz.com/)? – Phonolog Jul 06 '18 at 17:34

2 Answers2

0

I was able to find the answer myself and hence posting it for future reference by someone else.

Added the code inside ngAfterViewInit() and it seemed to work.

ngAfterViewInit() is called everytime when the page state changes, and view.instance.constructor.name gives you the current page's constructor name and you could simply compare it with your menu array to find out to which page you have navigated to and simply set it to active page.

Refer the complete code below

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 { HomePage } from '../pages/home/home';
import { ListPage } from '../pages/list/list';
import { GalleryPage } from '../pages/gallery/gallery';

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

  rootPage: any = HomePage;
  activePage: any;

  pages: Array<{title: string, component: any, active: boolean}>;

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

    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Home', component: HomePage, active: false },
      { title: 'List', component: ListPage, active: false },
      { title: 'Gallery', component: GalleryPage, active: false}
    ];

    this.activePage = this.pages[0];

  }

  ngAfterViewInit(){
    this.nav.viewDidEnter.subscribe((view) => {
      for(let i = 0 ; i < this.pages.length ; i++){
        if(this.pages[i].component.name == view.instance.constructor.name){
           this.activePage = this.pages[i];
           break;
        }
      }
    });
  }

  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.styleDefault();
      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);
    this.activePage = page;
  }

  checkActive(page){
    // console.log(page.title, this.activePage.title, page === this.activePage);
    return page === this.activePage;
  }
}
nijin
  • 556
  • 2
  • 16
0

I have another solution.

 <ion-item
        button
        [routerLink]="'about'"
        (click)="highlightIonItem('about')"
        [style]="{
          '--item-background': 'about' === activeMenuItem ? 'red' : ''
        }"
      >
        <ion-icon name="information-circle" slot="start"></ion-icon>
        <ion-label> {{ "root.about" | translate }}</ion-label>
 </ion-item>

public highlightIonItem(menuItemName: string): void {
       this.activeMenuItem = menuItemName;
       this._cdr.markForCheck();
}
:root {
  --item-background: red;
}

ion-item::part(native) {
    background: var(--item-background);
}

This is based on variable change based on menu name. Just simple click event. Hope this helps somebody.

Domorodec
  • 91
  • 12