NoBody
NoBody

Reputation: 53

Currently logged in user won’t display on the navbar until I manually refresh the browser

The last previous account name is displayed. It's only when I refresh the browser the displayed name changes to the current logged in account.

below is the Auth service.

 import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from 'src/environments/environment';
import { map } from 'rxjs/operators';
import { DefaultUrlSerializer } from '@angular/router';
import { JwtHelperService } from '@auth0/angular-jwt';
import { Observable } from 'rxjs';
import { yearsPerPage } from '@angular/material/datepicker';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  baseUrl = environment.apiUrl + 'auth/';
  decodedToken: any;
  jwtHelper = new JwtHelperService();


  constructor(private http: HttpClient) { }

  login(model: any) {
    return this.http.post(this.baseUrl + 'login', model)
      .pipe(
        map((response: any) => {
          const user = response;
          if (user) {
            localStorage.setItem('token', user.token);
            localStorage.setItem('user', JSON.stringify(user.user));
            this.decodedToken = this.jwtHelper.decodeToken(user.token);
            localStorage.setItem('role', JSON.stringify(this.decodedToken.role));
          }
        })
      );
  }
  register(model: any) {
    return this.http.post(this.baseUrl + 'register', model, { responseType: 'text' });
  }

  loggedIn() {
    const token = localStorage.getItem('token');
    return !this.jwtHelper.isTokenExpired(token);
    window.location.reload();
  }

  role() {
    return localStorage.getItem('role');
  }

}

I’m getting the logged in details from the local storage and storing the details into a variable called userDisplayName in the navbar component. As you can see below the code is in ngONInit method. “this.userDisplayName = JSON.parse (localStorage.getItem('user'));”

import { AddTaskComponent } from './../addTask/addTask.component';
import { AuthService } from './../_services/auth.service';
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { UpdateTaskComponent } from '../updateTask/updateTask.component';
import { Router } from '@angular/router';
import { UserMemberService } from '../_services/userMember.service';
import { StateStorageService } from '../_services/stateStorage.service';

@Component({
  selector: 'app-navigation-bar',
  templateUrl: './navigationBar.component.html',
  styleUrls: ['./navigationBar.component.css']
})
export class NavigationBarComponent implements OnInit {
  model: any = {};
  loginReactiveForm: FormGroup;
  role;
  users: any[];
  userAuthorised: boolean;
  searchTask: FormControl;
  Username: string;
  userDisplayName;


  constructor(
    private authService: AuthService,
    public dialog: MatDialog,
    private router: Router,
    private userMemberService: UserMemberService,
    private stateStorageService: StateStorageService) { }

  ngOnInit() {
    this.initForm();
    this.isUserAdmin();
  //  this.userDisplayName = this.authService.login(this.model);
    this.userDisplayName = JSON.parse (localStorage.getItem('user'));
    console.log(this.role);
  }




  login() {
    this.model.username = this.loginReactiveForm.value.username;
    this.model.password = this.loginReactiveForm.value.password;



    this.authService.login(this.model).subscribe(next => {
      this.loadUsers();
      this.router.navigateByUrl('/CalendarView');
      this.isUserAdmin();
      }, error => {
        console.log('failed to login');
      });
  }



  isUserAdmin() {
    // get users role
    this.role = JSON.parse(localStorage.getItem('role'));
    console.log('this is role = ' + this.role);
  // if user is not an Admin
    if (this.role !== 'Admin') {
      this.userAuthorised = false;
      console.log('value of auth is = ' + this.userAuthorised );
    } // if user is an Admin
    else {
      // list of users for the drop down
      this.userAuthorised = true;
      console.log('value of auth is = ' + this.userAuthorised );
    }
  }

  loadUsers() {
    this.userMemberService.getUsers().subscribe((data) => {
      this.users = data;
      this.stateStorageService.setUserMemberStorage(this.users);
    }, error => {
      console.log(error);
    });
  }

  initForm() {
    this.loginReactiveForm = new FormGroup({
      username: new FormControl(),
      password: new FormControl()
    });

    this.searchTask = new FormControl();

  }




  // has the user logged in
  loggedIn() {
    return this.authService.loggedIn();
  }

  loggedOut() {
    const token = localStorage.removeItem('token');
    const username = localStorage.removeItem('user');
    const userId = localStorage.removeItem('role');
    localStorage.removeItem('user');
    }
}

Below is the html

<nav class="navbar navbar-expand-md navbar-dark bg-dark">

    <ul *ngIf="!loggedIn()" class="navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link">
          <span class="sr-only"></span></a>
      </li>      
    </ul>   
    
    
    <form *ngIf="!loggedIn()" class="form-inline my-2 my-lg-0" [formGroup]="loginReactiveForm" 
      (ngSubmit)="login()">
      <input formControlName="username" class="form-control mr-sm-2" 
        type="text" placeholder="Username" aria-label="username">
      <input formControlName="password" class="form-control mr-sm-2" 
        type="password" placeholder="Password" autocomplete="off" aria-label="password">
      <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Login</button>
    </form>

    <div *ngIf="loggedIn()"  class="username"  style="position:relative; left:70%;  color: white ;" >Username: {{userDisplayName.username}}</div>
    

    <div style="position:relative; left:85%">
       <button *ngIf="loggedIn()" class="btn btn-outline-success float-right" 
      type="submit" (click)="loggedOut()" [routerLink]="['/login']">Log Out</button>
    </div>



</nav>
     

Why is is that the loggedin user is only displayed once the browser has been refreshed? I'm currently logged in as “Matt Briggs” but it shows “Sallyjones” on the navbar in the image. Link to the image is here

Upvotes: 0

Views: 1445

Answers (3)

lopamudra
lopamudra

Reputation: 49

you can directly call it from your server to html page

    get loggedInUser(): any {
    const uname = localStorage.getItem('uname');
    return uname;
    } 

In your html page

<li><a *ngIf="auth.isLoggedIncheck"><span class="glyphicon glyphicon-log-in"></span> Welcome{{auth.loggedInUser| uppercase}} </a> </li>

   

Upvotes: 0

b_it_s
b_it_s

Reputation: 714

Problem

The problem in your code is that you only set userDisplayName once in ngOnInit. NgOnInit is only called once when the component is initialised. So this is why you need to refresh to see the new user from localstorage. There's no other place where you change or update userDisplayName...

Solution

I think your code could use a little refactoring to make it work like you expect. You're putting to much logic in your component code.

Save your decodedToken in a currentUser subject which is exposed as an observable ==> By doing this, you can subscribe to this observabel in your component's ngOnInit function. This way every change will be shown in your component too.

This is a tutorial which gives a complete overview of how you can implement authentication in Angular. Give it a good read and try this out in your code. https://jasonwatmore.com/post/2020/07/09/angular-10-jwt-authentication-example-tutorial#authentication-service-ts

Upvotes: 1

joshvito
joshvito

Reputation: 1563

this sounds like a change detection problem. Can you use a Subject to store the userDisplayName?

e.g.

export class NavigationBarComponent implements OnInit {
...
  userDisplayName = new Subject<{username: string}>;

...
const _u  = JSON.parse(localStorage.getItem('user'));
this.userDisplayName.next(_u);

then in your template

<div *ngIf="loggedIn()"
  class="username"
  style="position:relative; left:70%;  color: white ;" >
    Username: {{(userDisplayName | aasync)?.username}}
</div>

Using a subject will cause ng to redraw the ui when the value of userDisplayName changes.

I am guessing that ng is drawing the dom on init, when there is an old value in userDisplayName and doesn't know the value has changed. Using a subscribable will fix that.

Upvotes: 0

Related Questions