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
asyncpipe to check for the authentication status - I suggest you to use only one variable in
localStorageand then pipe this to theisLoggedInstatus (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);
}
}
