Struggling to find a solution to this issue, I've spent hours searching online without success.
The challenge at hand involves updating the menu item in my navigation bar template to display either "login" or "logout" based on the user's current login status.
I utilize two distinct services for this task: the authService, which handles user authentication processes, and the sessionService, responsible for managing session-related functionalities.
The goal is to automatically update components whenever a user logs in or out by syncing with changes made in the localStorage via the sessionService. While attempts with .subscribe and .map have been unsuccessful, calling this.loggedIn.next(this._sessionService.isSetUserSession()); within the login and logout methods seems to be the only approach that works.
What am I missing here?
navbar.component.html
<div class="dropdown-menu" aria-labelledby="dropdownAccount">
<ng-template *ngIf="(loggedIn$ | async); else elseDiv;">
<a class="nav-link" href="javascript:void(0)" (click)="logout()">LOGOUT</a>
</ng-template>
<ng-template #elseDiv>
<a class="nav-link" href="javascript:void(0)"(click)="login(...);">
LOGIN
</a>
</ng-template>
</div>
navbar.component.ts
import {Component, OnInit} from '@angular/core';
import {AuthService} from '../services/auth.service';
@Component({
moduleId: module.id,
selector: 'app-nav-bar',
templateUrl: 'navbar.component.html',
styleUrls: ['./navbar.component.css'],
})
export class NavbarComponent implements OnInit {
isNavbarCollapsed = true;
loggedIn$: any;
constructor(
private authService: AuthService) {
}
ngOnInit() {
this.loggedIn$ = this.authService.isLoggedIn;
}
}
auth.service.ts
import {Injectable} from '@angular/core';
import {Http, Response} from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
import {IUser} from '../entities/user';
import {SessionService} from './session.service';
import {Router} from '@angular/router';
import {Subject} from 'rxjs/Subject';
@Injectable()
export class AuthService {
private loggedIn: Subject<boolean> = new Subject<boolean>();
get isLoggedIn() {
return this.loggedIn.asObservable();
}
constructor(private _http: Http,
private _sessionService: SessionService,
private _router: Router) {
this.loggedIn.next(this._sessionService.isSetUserSession());
}
login(user: IUser) {
return this._http.get('assets/api/responseSuccess.json?email=' + user.email + '&password=' + user.password)
.map((responseLogin => {
const jsonResponse = responseLogin.json();
if (jsonResponse.response === 'success') {
const userResponse: IUser = jsonResponse.user;
this._sessionService.setUserSession(userResponse);
//this.loggedIn.next(this._sessionService.isSetUserSession()); ==> This makes it work, but I want the session to sync automatically without manual calls
return true;
} else {
console.log("error logging in");
return false;
}
}));
}
logout() {
this._sessionService.clearUserSession();
// this.loggedIn.next(this._sessionService.isSetUserSession()); => Same here
return this._router.navigate(['/']);
}
}
session.service.ts
import {Injectable} from '@angular/core';
import {IUser} from '../entities/user';
import {isNullOrUndefined} from 'util';
import {Subject} from "rxjs/Subject";
@Injectable()
export class SessionService {
isSetUserSession(): boolean {
return !!localStorage.getItem('user');
}
clearUserSession() {
localStorage.removeItem('user');
}
setUserSession(user: IUser) {
localStorage.setItem('user', JSON.stringify(user));
}
}