How to pass storage (User session) data to side menu ionic 5?

i am new in ionic and started from youtube tutorials , i created a crud in ionic using PHP, my sql in success login i redirect to home page and by using home.page.ts i can get storage data in home.page.html, but i am not able to pass user storage data in side menu to show user name in side menu, i tried in app. component. ts to get storage data and pass to side menu which html is in app. component. html but its not showing on first login but after login when i refresh it shows name that’s because it is added storage else condition in app. component. ts i even added that method in after ready but still no luck i need help on this pls.

======================================================================

app.component.ts

import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { Storage } from '@ionic/storage';
import { NavController } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent {

  datastorage: any;
  patient_name: string;
  patient_no: string;

  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private storage: Storage,
    public navCtrl: NavController
  ) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      this.statusBar.styleDefault();
      this.splashScreen.hide();
      
       this.storage.get('storage_xxx').then((res)=>{
             if(res==null)
             {
               this.navCtrl.navigateRoot('/login');
             }
             else
             {
               console.log(res);
              this.datastorage=res;
              this.patient_name = this.datastorage.patient_name;
              this.patient_no = this.datastorage.patient_no;
              this.navCtrl.navigateRoot('/home');
             }
        });
      
    });

   this.storage.get('storage_xxx').then((res)=>{
     if(res==null)
     {
       this.navCtrl.navigateRoot('/login');
     }
     else
     {
       console.log(res);
      this.datastorage=res;
      this.patient_name = this.datastorage.patient_name;
      this.patient_no = this.datastorage.patient_no;
      this.navCtrl.navigateRoot('/home');
     }
   });

  }
}

app.component.html

<ion-app>
  <ion-menu menuId="main-menu" contentId="main">
    <ion-content>
     <div class="menu-header-bg"></div>
     <div class="header-content">
       <img src="../assets/images/avatar.jpeg" alt="">
       <ion-label>
         <h2>{{patient_name}}</h2>
         <p>Num: {{patient_no}}</p>
       </ion-label>
     </div>
     <div class="action-button">
       <ion-button>
          <ion-icon slot="start" name="add"></ion-icon>Add Branch
        </ion-button>
     </div>
     <ion-list lines="none" class="menu-items">
      <ion-item>
        <ion-icon name="home"></ion-icon> Dashboard
      </ion-item>
       <ion-item>
         <ion-icon name="browsers-outline"></ion-icon> Post Session
       </ion-item>
       <ion-item class="active">
        <ion-icon name="flash"></ion-icon> Live Session
      </ion-item>
      <ion-item>
        <ion-icon name="heart-outline"></ion-icon> Library
      </ion-item>
      <ion-item>
        <ion-icon name="chatbubble-ellipses-outline"></ion-icon> Message
      </ion-item>
      <ion-item>
        <ion-icon name="exit-outline"></ion-icon> Sign Out
      </ion-item>
     </ion-list>
    </ion-content>
  </ion-menu>
  <ion-router-outlet id="main"></ion-router-outlet>
</ion-app>

login.page.ts

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { ToastController, LoadingController, AlertController, NavController } from '@ionic/angular';
import { AccessProviders } from '../../providers/access-providers';
import { Storage } from '@ionic/storage';
import { resolve } from 'dns';
import { promise } from 'protractor';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {

  user_login_name: string="";
  login_password: string="";

  disabledButton;

  constructor(
    private router : Router,
    private toastCtrl : ToastController,
    private loadingCtrl : LoadingController,
    private alertCtrl : AlertController,
    private accessPrvds : AccessProviders,
    private storage: Storage,
    public navCtrl: NavController
  ) { }

  ngOnInit() {
  }

  ionViewDidEnter()
  {
    this.disabledButton=false;
  }

  openRegister()
  {
    this.router.navigate(['/register']);
  }

  async tryLogin()
  {
   if(this.user_login_name==""){
      this.presentToast("Username is required");
    }
    else if(this.login_password==""){
      this.presentToast("Password is required");
    }
    else{
      this.disabledButton=true;
      const loader = await this.loadingCtrl.create({
        message:"Please wait...",
      });
      loader.present();

      return new Promise(resolve=>{

        let body = {
          aksi : "process_login",
          user_login_name: this.user_login_name,
          login_password: this.login_password,
        }

        this.accessPrvds.postData(body, 'process_api.php').subscribe((res:any) => {
            if(res.success==true)
            {
              //console.log(res.result);
              loader.dismiss();
              this.disabledButton=false;
              this.presentToast('Login successfull');
              this.storage.set('storage_xxx',res.result); // store session data
              this.navCtrl.navigateRoot(['/home']);
            }
            else
            {
              loader.dismiss();
              this.disabledButton=false;
              this.presentToast('Username or password is wrong');
            }
        }, (err)=>{
              loader.dismiss();
              this.disabledButton=false;
              this.presentToast('Timeout!');
        });

      });

    }
  }

  async presentToast(a)
  {
    const toast = await this.toastCtrl.create({
      message:a,
      duration:1500
    });
    toast.present();
  }

  async presentLoader(a)
  {
    const loader = await this.loadingCtrl.create({
      message:"Please wait...",
    });
    loader.present();
  }

  async presentAlert(a) {
    const alert = await this.alertCtrl.create({
      header: a,
      backdropDismiss: false,
      buttons: [
        {
          text: 'Close',
          handler: (blah) => {
            console.log('Confirm Cancel: blah');
          }
        }, {
          text: 'Try Again',
          handler: () => {
            this.tryLogin();
          }
        }
      ]
    });

    await alert.present();
  }

}

I fear that however I try to soften this, it’s going to come across as overly harsh, but it is really worth the time to go through the Tour of Heroes in its entirety, and I would suggest forgetting everything you learned from YouTube before doing so.

I don’t want to discourage you by going through a detailed code review of what you’ve got here, as it wouldn’t really help you. Concentrate on getting a really solid grounding on what idiomatic Angular looks like: functional and reactive instead of imperative thinking, how DI works, how to leverage it when writing and using service providers, what sorts of functionality to put in templates, controllers, services, embedded components versus host pages.

1 Like

Hello @fahimakhtar,

You can do following steps:

  1. Create a provider i.e. data.provider.ts file.
  2. Declare a variable i.e. userData as public so that it can be accessible in all over the app.
  3. Get the data from storage in the constructor and assigned it to userData variable.

// src/app/providers/data.provider.ts
import { Injectable } from “@angular/core”;

@Injectable()
export class DataProvider {
public userData: string;
constructor( ) {
let data = JSON.parse(localStorage.getItem(“storedData”))
this.userData = data;
}
}
4. Now in app.module.ts file, import the data provider and also improve providers array by adding the data provider.
5. You also need to import provider in login component and initialize the variable with the appropriate value.
6. To display the data on side menu, import the data provider on app.component.ts file, and define in the constructor as public because we need to show the data on html page.
7. Then you can access the data variable on app.component.html page like {{ dataProvider.userData }}

HTH!

1 Like

Thanks … It worked for me !!

I guess I should probably comment in my role as the forum’s resident funpire.

localStorage is worthless. Whatever you’re trying to do with it, there’s a better way. If you need to preserve information across app runs, you can’t rely on localStorage to still be there. Ionic Storage, which can use IndexedDB under the hood, provides better persistence guarantees, and eliminates any need for manual JSON marshalling or unmarshalling.

Virtually every time I’ve ever exposed raw data out of providers, I’ve ended up regretting it. At some point, userData will change while the app is running. When that happens, you’re basically toast. You have no way of even knowing what components or other services have references to what is now stale data. Usually at this point, another thread gets created here asking how to use lifecycle events to refresh stale data in pages, and we go further down the rabbit hole of doom.

So I always expose business objects (or collections thereof) as Observables from services. Typically, they’re Subjects underneath, but ordinary clients should not know that, so that you can keep tight control over who is allowed to update what should be the single source of truth in the app for this information.