Home > Software engineering >  How to let app.component know that user has logged in or logout Angular
How to let app.component know that user has logged in or logout Angular

Time:11-08

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 the isLoggedIn 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);
  }
}

  • Related