First time when web application loads, app.component
is getting called and navigationbar #1
showing up. Now when user login I want to load navigationbar #2
from app.component
(or let app.component
UI know that user has logged in) so that ng-template
can update UI and set navigationbar #2
.
This is my code in app.component.html
file
<div *ngIf="session === 'true'; else NoUserTemplete">
<app-app-navigation-bar-admin></app-app-navigation-bar-admin>
</div>
<ng-template #NoUserTemplete>
<app-navigation-bar></app-navigation-bar>
</ng-template>
app.component.ts
file
constructor() {
this.session = localStorage.getItem('isloggedin')
}
Below method called, when user hit Login button in login.component
UserLogin()
{
this.submitted = true;
if(this.loginForm.invalid)
{
localStorage.removeItem("isloggedin");
return
}
let data = { userName: this.loginForm.value.userName, txtemail:this.loginForm.value.txtEmail}
localStorage.setItem("userinfo", JSON.stringify(data));
localStorage.setItem('isloggedin','true');
this.router.navigate(['/home']);
}
Basically what I need is, whenever localStorage
's isloggedin variable
is getting changed app.component
should be aware about that and update the UI. How can I do that ?
CodePudding user response:
You can build a service to manage the isLoggedIn
variable from the local storage. This service can also expose whatever is currently saved in the local storage at the moment. The benefit of this is that you can also expose some observable, to which you can subscribe from whichever component is interested in knowing when this variable changes (including AppComponent
).
@Injectable({providedIn: 'root'})
export class LoginService {
private isLoggedInSource = new ReplaySubject<boolean>(1);
public isLoggedIn$: Observable<boolean>;
constructor() {
this.isLoggedIn$ = this.isLoggedInSource.asObservable();
// sync initial value
syncLoggedIn();
}
updateLoggedInStatus(isLoggedIn: boolean) {
localStorage.setItem('isloggedin', isLoggedIn ? 'true' : 'false');
syncLoggedIn();
}
}
private syncLoggedIn(): void {
this.isLoggedInSource.next(localStorage.getItem('isloggedin') === 'true');
}
Then in your login component you can inject the LoginService
to be able to update the global isLoggedIn
status.
constructor(private loginService: LoginService) {}
UserLogin()
{
this.submitted = true;
if(this.loginForm.invalid)
{
this.loginService.updateLoggedInStatus(false);
return
}
let data = { userName: this.loginForm.value.userName, txtemail:this.loginForm.value.txtEmail}
localStorage.setItem("userinfo", JSON.stringify(data));
this.loginService.updateLoggedInStatus(true);
this.router.navigate(['/home']);
}
// in the logout method
// you also need to call this.loginService.updateLoggedInStatus(false);
Inside the AppComponent
you can inject the same service to listen for the changes. Turn your session
boolean property to an observable instead and use the async
pipe:
session$: Observable<boolean>;
constructor(private loginService: LoginService) {
this.session$ = loginService.isLoggedIn$;
}
And finally, in the template of your app component you can use the session$
observable with the async
pipe to decide which toolbar to show:
<div *ngIf="session$ | async; else NoUserTemplete">
<app-app-navigation-bar-admin></app-app-navigation-bar-admin>
</div>
<ng-template #NoUserTemplete>
<app-navigation-bar></app-navigation-bar>
</ng-template>
CodePudding user response:
You should definitely use a service for this.
Notes:
- You can inject this service in any component (e.g. AppComponent) and then use the
async
pipe to check for the authentication status - I suggest you to use only one variable in
localStorage
and then pipe this to theisLoggedIn
status (also as an observable)
Here is an example implementation:
const USER_INFO_KEY = 'userinfo';
@Injectable({providedIn: 'root'})
export class AuthService {
private _userInfo$ = new BehaviorSubject<UserInfo | null>(
JSON.parse(localStorage.getItem(USER_INFO_KEY))
);
public userInfo$ = this._userInfo$.asObservable();
public isLoggedIn$ = this.userInfo$.pipe(
map((userInfo) => Boolean(userInfo))
);
setUserInfo(userInfo: UserInfo | null) {
localStorage.setItem(USER_INFO_KEY, JSON.stringify(userInfo));
this._userInfo$.next(userInfo);
}
}