1
\$\begingroup\$

I have a small website I'm working on as a hobby and I created a login page/home page so far. I wanted to get the basic login/logout functionality going before filling out the main part of my site. I have the authentication with the server working, auth guards, and things like that. I wanted to create some functionality for my NavBar so that I could have a single component and not have to have a LoggedInNavBar and LoggedOutNavBar kind of scenario, so I hatched the idea of, "Hey, what if my NavBar was aware of the state of being logged in or not?". Well, this was entirely new territory for me (as most of Angular is, I have a part of a project at work that is built in Angular, and I don't work on it super often so I'm trying to keep my skills sharp in that regard).

So, here is what I came up with. I have a AuthService class which provides the capability of logging in and out. I figured this service would provide a nice entry point to be able to subscribe to an observable which would notify me of authentication state changes.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { JwtHelper } from 'angular2-jwt';
import { Observable, Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  private static readonly apiUrl: string = "https://localhost:44398/api/auth/"
  private static readonly loginUrl: string = AuthService.apiUrl + "login";

  private $state: Subject<boolean>;

  constructor(private http: HttpClient, private jwtHelper: JwtHelper) {    
    this.$state = new Subject<boolean>();
  }

  login(userLogin: UserLogin, onData: Function = null, onError: Function = null, onComplete: Function = null) {
    this.http.post(AuthService.loginUrl, userLogin, {
      headers: new HttpHeaders({
        "Content-Type": "application/json",
        "Access-Control-Allow-Origin": "*"
    })}).subscribe(
      response => {        
        onData(response);
        this.$state.next(true);
      },
      error => {
        onError(error)
        this.$state.next(false);
      },
      () => onComplete()
    )
  }

  logOut() {
    localStorage.removeItem("jwt");
    this.$state.next(false);
  }

  getStateObservable(): Observable<boolean> {
    return this.$state.asObservable();
  }
}

My login page uses the login method from AuthService. The reason I didn't just return the observable was because I was thinking I needed to be able to inject my Subject calls in after my own onData (next), onError, and onComplete methods. It seems to work well enough, but I'm not certain if this is hacky or not.

Here is the .ts for my NavBar:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-nav-bar',
  templateUrl: './nav-bar.component.html',
  styleUrls: ['./nav-bar.component.css']
})
export class NavBarComponent implements OnInit {
  $loggedInState: Observable<boolean>;

  constructor(private router: Router, private authService: AuthService) {
  }

  ngOnInit() {
    this.$loggedInState = this.authService.getStateObservable();    
  }

  onLogOutClick() {
    this.authService.logOut();
    this.router.navigate(["login"]);
  }
}

Nothing fancy here except I call into getStateObservable to be able to subscribe to the logged in state. The HTML for NavBar is really simple right now, just a title and a "Log Out" or "Log In" button. I haven't finished fleshing things out here so don't mind the fact that both buttons use the same function call.

<mat-toolbar color="primary">
  <span>Auction House Price Tracker</span>
  <span class="fill-remaining-space"></span>
  <div *ngIf="$loggedInState | async;then logged_in else not_logged_in"></div>  
  <ng-template #logged_in><h1>LOGGED IN</h1><a mat-button (click)="onLogOutClick()">Log Out</a></ng-template>
  <ng-template #not_logged_in><h1>LOGGED OUT</h1><a mat-button (click)="onLogOutClick()">Log In</a></ng-template>
</mat-toolbar>

I'd appreciate some tips here on if I'm doing something grossly wrong, if there is inefficiencies, memory leaks, or whatever (I assume the NavBar's subscription is the duration of the session, is there a need to ever unsubscribe something like that?).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.