View don't update with *ngIf in Ionic 3 side menu

I’ve a side menu and a ion-spinner inside. I want the spinner to be removed after a request. For this, I’m trying to use *ngIf, but, isn’t working as expected.

app.html:


<ion-menu [content]="content" side="left" id="menuMenu" class="main-menu" (ionOpen)="menuMenuOpened()">
    <ion-content>
        <ion-spinner *ngIf="!menuLoaded"></ion-spinner>
    </ion-content>
</ion-menu>

<ion-nav #content [root]="rootPage" swipeBackEnabled="false"></ion-nav>

app.components.ts:

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

import { UserProvider } from '../providers/user/user';
import { TabsPage } from '../pages/tabs/tabs';

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

  menuOpened: boolean = false;
  menuLoaded: boolean = false;

  rootPage: any = TabsPage;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, private userProvider: UserProvider) {
    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.
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }

  menuMenuOpened() {
    if (!this.menuOpened) {
      this.menuOpened = true;

      console.log("Menu opened for the first time");
      console.log(this.menuLoaded); // false
      
      this.userProvider.loadMenu().subscribe(data => {
        const json = JSON.parse((data as any)._body);

        if (json.error) {
          console.log(json.error);
        } else {
          this.menuLoaded = true;
          console.log(this.menuLoaded); // true

          // console.log(json[0]);
        }
      }, error => {
        console.log(error);
      });
    }
  }
}

When I open the menu, spinner is there (as expected), however, even after I change the value of menuLoaded to true the spinner remains visible. The value is updated and the spinner disappears only when I enter some other tab or click on the hamburger icon for the menu to open again (if I drag the menu both to open and close it still does not work).

How can I fix it?

Run it in ngZone.

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

...

constructor (private ngZone: ngZone)

...
this.ngZone.run(() => {
     this.menuLoaded = true;
     console.log(this.menuLoaded); // true
})
3 Likes

Amazing! It worked! Can you explain why we have to use NgZone in this case? (I’ve used *ngIf in other cases and it worked well without needing anything more.)

1 Like

Because it is wrapped in a private provider so it is another zone, outside component zone :wink:

1 Like