Reputation: 3077
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
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
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