Making the UI reactive to the user authentication status

All right, so unauthorized users cannot access the task editor form component. However, having an unresponsive link in our main toolbar is definitely not good, so we should leverage the Observable features of the AuthenticationService to flip the UI whenever there is a change in the user login status.

Right now, the nav bar features the Login link that leads the user login form page. What we want to do is to hide the Publish Task link and make sure we only display it when the user is logged in, no matter where and how this login procedure was undertaken. On the other hand, we also want to offer the end user a Logout link when logged in, so they can shut down his session in confidence. This logout link should be made available for logged in users only. Access to the protected component by hardcoding URLs is not a concern, since the @CanActivate decorator will do its job to keep undesired users away.

Now that we have described the requirements, let’s put them into practice. Open the top root component file and update its implementation (it remained empty until now). We will need the AuthenticationService and the Router dependencies to do so, so make sure to import them at the top of the file:

app/app.component.ts

import { Component } from '@angular/core';
import { 
  SHARED_PROVIDERS,
  AuthenticationService } from './shared/shared';
import { HTTP_PROVIDERS } from '@angular/http';
import {
  ROUTER_PROVIDERS,
  RouteConfig,
  ROUTER_DIRECTIVES,
  Router } from '@angular/router-deprecated';
// Rest of import statements remain the same
…

With the tokens properly declared in the import statements, we can move on and provide an implementation for the AppComponent class:

app/app.component.ts

...
export default class AppComponent {
  userIsLoggedIn: boolean;

  constructor(
    private authenticationService: AuthenticationService,
    private router: Router) {
    authenticationService.userIsloggedIn.subscribe(isLoggedIn => {
      this.userIsLoggedIn = isLoggedIn;
    });
  }

  logout($event): void {
    $event.preventDefault();

    this.authenticationService.logout().then(success => {
      if (success) {
        this.router.navigateByUrl('/');
      }
    });
  }
}

We have declared a userIsLoggedIn Boolean field, which will change its value every time the observable userIsloggedIn member of the injected AuthenticationService type changes its value. We also injected the Router type and created a new component method named logout() that will wipe out the user session and redirect the user to the root page upon signing out from the application.

This gives us the chance to wrap up the application UI by updating the root component template to make the sensible links fully reactive to these changes:

app/app.component.html

<nav class="navbar navbar-default navbar-static-top">
  <div class="container">
    <div class="navbar-header">
      <strong class="navbar-brand">My Pomodoro App</strong>
    </div>
    <ul class="nav navbar-nav navbar-right">
      <li><a [routerLink]="['TasksComponent']">Tasks</a></li>
      <li><a [routerLink]="['TimerComponent']">Timer</a></li>
      <li *ngIf="userIsLoggedIn">
        <a [routerLink]="['TaskEditorComponent']">Publish Task</a>
      </li>
      <li *ngIf="!userIsLoggedIn"><a [routerLink]="['LoginComponent']">Login</a>
      </li>
      <li *ngIf="userIsLoggedIn">
        <a href="#" (click)="logout($event)">Logout</a>
      </li>
    </ul>
  </div>
</nav>
<router-outlet></router-outlet>

Give it a try! Reload the application, check the links available at the nav bar, head over to the login page, proceed to login with the credentials, and check the nav bar again… Magic!