Reputation: 38
I'm trying to get the current user as an observable in the authentication service, so I want to display the current user even though the page is reloading
Everything is working fine, but I cannot get current user after page reload
On AuthService:
private currentUserSubject: BehaviorSubject<any>;
public currentUser: Observable<any>;
constructor(private httpClient: HttpClient,public router: Router) {
this.currentUserSubject = new BehaviorSubject(JSON.parse(localStorage.getItem('currentUser')));
this.currentUser = this.currentUserSubject.asObservable();
}
login(user: User) {
return this.httpClient.post<any>(`${this.API_URL}/users/login`, user)
.subscribe((data: any) => {
localStorage.setItem('access_token', data.token)
this.getUserProfile(data.user._id).subscribe((res) => {
--->>>> this.currentUserSubject.next(res.nom);
this.router.navigate(['/profile/' + res._id]);
})
})
}
On PageComponent:
currentuser;
ngOnInit() {
this.currentuser = this.authService.getCurrentUser()
console.log("my user s heeere " + this.currentuser)
}
Result
my user heeere JOETEST
After page reload
my user heeere null
Upvotes: 1
Views: 6520
Reputation: 4022
To handle User session Build a dedicated Auth Functionality
It follows the separation of concern and single responsibility principle and makes your code highly maintainable. I am posting a complete solution for later reference.
auth.service.ts
import { Injectable, PLATFORM_ID, Inject } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { AuthApiService } from '../api/auth.api';
import { tap, take, first } from 'rxjs/operators';
import { isPlatformBrowser } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private readonly CAH_TOKEN = 'CahToken';
private readonly CAH_USERNAME = 'username';
private logger: BehaviorSubject<boolean> = new BehaviorSubject(false);
constructor(private api: AuthApiService, @Inject(PLATFORM_ID) private platformId) {
this.logger.next(this.isUserLoggedIn());
}
/** Subscribe to know automatically whenever login status changes */
public isLoggedIn = () => this.logger.asObservable();
public logout = () => this.api.logout().pipe(tap(_ => this.deleteUser()));
public login = (username, password) => this.api.login(username, password).pipe(tap(_ => { if (_.success) { this.saveUser(_); } }));
public getToken = () => localStorage.getItem(this.CAH_TOKEN);
public getUserName = () => localStorage.getItem(this.CAH_USERNAME);
private saveUser(res): void {
localStorage.setItem(this.CAH_TOKEN, res.data.token);
localStorage.setItem(this.CAH_USERNAME, res.data.username);
this.logger.next(true);
}
private deleteUser(): void {
localStorage.removeItem(this.CAH_TOKEN);
localStorage.removeItem(this.CAH_USERNAME);
this.logger.next(false);
}
private isUserLoggedIn(): boolean {
const user = isPlatformBrowser(this.platformId) && localStorage.getItem(this.CAH_TOKEN) ? true : false;
return user;
}
}
auth.api.ts
// API FOR LOGIN/LOGOUT
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthApiService {
constructor(private http: HttpClient) { }
login(username: string, password: string): Observable<any> {
const url: string = environment.cahServerUrl + 'api/users/auth/login';
const body = { username, password };
return this.http.post(url, body);
}
logout(): Observable<any> {
const url: string = environment.cahServerUrl + 'api/users/auth/logout';
const body = {};
return this.http.post(url, body);
}
}
export interface LoginRes {
success: boolean;
message: string;
data: any;
}
In someComponent.ts
// WILL TELL AUTOMATICALLY WHENEVER USER LOGSIN OR LOGOUT
this.auth.isLoggedIn().subscribe(_ => {
this.isLoggedIn = _;
if (_) { this.userName = this.auth.getUser().username; }
});
In login.component.ts
// TO MAKE USER LOGIN
this.auth.login(username, password).subscribe(this.handleLogin, this.handleLoginError, () => { this.isBtnClicked = false; });
handleLogin = (res: LoginRes) => {
if (res.success) {
this.router.navigate(['/']);
}
else {
this.message = res.message;
}
}
handleLoginError = err => {
console.log(err);
}
Upvotes: 0
Reputation: 4022
To persist data(user in this case) you need to save data in LocalStorage.
During Login:-
login(user: User) {
...
.subscribe((data: any) => {
localStorage.setItem('access_token', data.token)
localStorage.setItem('currentUser', data.user)
--->>>> this.currentUserSubject.next(data.user);
...
}
In Constructor:-
constructor(private httpClient: HttpClient,public router: Router) {
this.currentUserSubject = new BehaviorSubject(localStorage.getItem('currentUser') || '');
this.currentUser = this.currentUserSubject.asObservable();
}
Upvotes: 1
Reputation: 898
The most simple answer is to store the value in localstorage. A little bit more harder but on a long term it pays off is the state management libraries in angular. I like to use Akita for this purpose.
Akita has the feature to store the current state in localstorage without any interaction needed even after page reload it will automatically read data from there.
Docs and source is available on github https://datorama.github.io/akita/
Upvotes: -1
Reputation: 358
You can not hold data in service after refresh. All the page lifecycle of the components and service runs all over again on refresh.
Instead access data from localStorage/sessionStorage. So your ngOnInit
will be like
const loggedInUser= (JSON.parse(localStorage.getItem('currentUser'))
;
if(!loggedInUser) {this.currentuser = this.authService.getCurrentUser()}
Upvotes: 3