GoGo
GoGo

Reputation: 3077

Navmenu items doesn't change unless it's refreshed it.

I have an angular app that has authentication system. Inside the navmenu, I have login, logout and a text that displays username. It works just fine, however, when the user logged in, I still see the same navbar. login should be gone and logout along with username text should be there. But it's not. They are there only when user refreshes the page. I don't know what I'm missing.

Here is my navmenu.component.html

<li *ngIf="!currentUser"><a [routerLink]="['/login']"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
<li *ngIf="currentUser"><a (click)="logout()"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li>
<li *ngIf="currentUser"><a><span class="glyphicon glyphicon-user"></span> {{ currentUser.firstName }} {{ currentUser.lastName }}</a></li>

And here is my navmenu.component.ts code:

import { Observable } from 'rxjs';
import { User } from './../../models/user';
import { Router } from '@angular/router';
import { AuthService } from './../../services/auth.service';
import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'nav-menu',
    templateUrl: './navmenu.component.html',
    styleUrls: ['./navmenu.component.css']
})
export class NavMenuComponent implements OnInit {
    currentUser: User;

ngOnInit() {
    this.currentUser = JSON.parse(localStorage.getItem('currentUser') || '');
}


constructor(private authService: AuthService, private router: Router) {  }


   logout() {
      this.authService.logout();
      this.router.navigate(['/home']);
   }
}

Lastly, here is my app.component.html file looks like:

<nav-menu></nav-menu>
<router-outlet></router-outlet>

Upvotes: 0

Views: 103

Answers (2)

AVJT82
AVJT82

Reputation: 73367

You can use a BehaviorSubject that checks if there is a user in localStorage and also emits changes in the status.

Service:

private user = new BehaviorSubject<any>(JSON.parse(localStorage.getItem('currentUser')))
public user$ = this.user.asObservable();

setUser(user) {
  localStorage.setItem('currentUser', JSON.stringify(user))
  this.user.next(true)
}

we call setUser() when the status changes. And every subscriber get's the status.

Login:

login() {
  this.authService.setUser({user: 'Admin'});
}

and each component that you want to listen to, add this to constructor:

constructor(private authService: Service) {  
  authService.user$.subscribe(val => {
    this.currentUser = JSON.parse(localStorage.getItem('currentUser'))
  })
}

and then of course when you want to log out user, do...

logout() {
  this.authService.setUser(null)
}

Upvotes: 0

Vitalii Chmovzh
Vitalii Chmovzh

Reputation: 2943

ngOnInit will be called only once, so I suggest to do the following:

auth.service.ts

// Your code here
authStateChanged: Subject<AuthState> = new Subject<AuthState>();
// Your code here

auth-state.enum.ts

export enum AuthState {
    Authorized,
    Unauthorized
}

component.ts

Leave everything as is, just change ngOnInit slightly.

ngOnInit() {
    this.authService.authStateChanged.subscribe(
        authState => { this.refreshCurrentUser(); }
    )
}

refreshCurrentUser() {
    this.currentUser = JSON.parse(localStorage.getItem('currentUser') || '');
}

You can add more login to check authState, this is just basic example that will work in your case.

Now inside your auth.service when you do logon, on success simply do:

this.authStateChange.next(AuthState.Authorized);

Upvotes: 1

Related Questions