Display username once logged in (exactly like Conference App)


#1

I’m having trouble displaying the username of a user once they are logged in, and what I find frustrating is that I believe I am doing it identical to the Ionic Conference App, however I am getting a different result.

Just to be clear, this is what I am trying to accomplish:

I have tried to take the same approach as the Ionic Conference App whereby the username is stored in the local Storage upon login (by the UserData provider), and then retrieved from local Storage on the AccountPage using ngAfterViewInit.

However, this is not working as I would like it to. Basically when I login the username value is displayed on the home page as null, however if I refresh the Local Storage (via Chrome Dev Tools) I can see that it has successfully been written to local storage:

What I would expect is that the value is written to local storage AND displayed on my home page.

It would be greatly appreciated if someone could review my code below to tell me where I’ve gone wrong. Please note that there’s no back-end to this login, and the username is simply passed to the UserData provider upon clicking the Login button (which is what the Ionic Conference App does).

pages/login/login.html

<ion-header>
  <ion-navbar>
    <ion-title>Login</ion-title>
  </ion-navbar>
</ion-header>
<ion-content scroll="false">
	<form #loginForm="ngForm" novalidate>
		<ion-item>
			<ion-label stacked>E-mail</ion-label>
			<ion-input [(ngModel)]="login.username" name="username" type="text" #username="ngModel" spellcheck="false" autocapitalize="off" required>
			</ion-input>
		</ion-item>
		<ion-item>
			<ion-label stacked>Password</ion-label>
			<ion-input [(ngModel)]="login.password" name="password" type="password" #password="ngModel" required>
			</ion-input>
		</ion-item>
	</form>
	<button ion-button (click)="onLogin(loginForm)" type="submit" color="primary" block>Login</button>
</ion-content>

pages/login/login.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { UserData } from '../../providers/user-data';
import { HomePage } from '../home/home';

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

	login: {username?: string, password?: string} = {};
  submitted = false;

  constructor(public navCtrl: NavController, public userData: UserData) {  }

  onLogin(form) {
    this.submitted = true;

    if (form.valid) {
      this.userData.login(this.login.username);
      this.navCtrl.push(HomePage);
    }
  }
}

pages/home/home.html

<ion-header>
  <ion-navbar>
    <ion-title>
      Home Page
    </ion-title>
    <ion-buttons end>
      <button ion-button icon-only (click)="logout()"><ion-icon name="power"></ion-icon></button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <p>Logged in as: {{username}}</p>
</ion-content>

pages/home/home.ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { UserData } from '../../providers/user-data';
import { LoginPage } from '../login/login';

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

  constructor(public nav: NavController, public userData: UserData) {
    
  }

  ngAfterViewInit() {
    this.getUsername();
  }

  getUsername() {
    this.userData.getUsername().then((username) => {
      this.username = username;
      console.log("Username is: " + this.username);
    });
  }

  logout() {
    this.userData.logout();
    this.nav.setRoot(LoginPage);
  }
}

providers/user-data.ts

import { Injectable } from '@angular/core';
import { Events } from 'ionic-angular';
import { Storage } from '@ionic/storage';

@Injectable()
export class UserData {
  HAS_LOGGED_IN = 'hasLoggedIn';

  constructor(public events: Events, public storage: Storage) {}

  login(username) {
    this.storage.set(this.HAS_LOGGED_IN, true);
    this.setUsername(username);
    this.events.publish('user:login');
  }

  logout() {
    this.storage.remove(this.HAS_LOGGED_IN);
    this.storage.remove('username');
    this.events.publish('user:logout');
  }

  setUsername(username) {
    this.storage.set('username', username);
  }

  getUsername() {
    return this.storage.get('username').then((value) => {
      return value;
    });
  }

  // return a promise
  hasLoggedIn() {
    return this.storage.get(this.HAS_LOGGED_IN).then((value) => {
      return value === true;
    });
  }
}

Thanks in advance!


#2
    let self = this;
  this.userData.getUsername().then((username) => {
    self.username = username;
    console.log("Username is: " + self.username);
  });
}```

"this." is getting lost when you have it inside the "then"

#3

I changed the getUsername() function in home.ts and I’m still getting the same result as before unfortunately - it hasn’t seemed to have made a difference.


#4

This issue is here:

this.userData.login(this.login.username);
      this.navCtrl.push(HomePage);

Your logging in and pushing at the same time essentially. So the HomePage is loading before the login has time to set the storage. You need to add a callback to the login with a boolean return or listen for the login successful event and then push to HomePage.


#5

I had similar error while displaying the logged in user name on the side menu inside app.component.ts.
I resolved this by getting the logged in username by getting the username in the ionViewDidLoad hook