Search code examples
angulartypescriptangular-ng-if

Angular 4 dynamic headers based on user type


I'm trying to implement a dynamic header component which changes based on user role.

Here is my header component

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
    currentUser:any;
  constructor(

  ) {
     this.currentUser = JSON.parse(localStorage.getItem('currentUser')); 

  }

  ngOnInit() {

  }

}

This is my header template

<nav class="navbar navbar-default" >
 <div class="collapse navbar-collapse" id="myNavbar">
  <ul class="nav navbar-nav navbar-right">
    <li class="menu_item" *ngIf="!currentUser"><a [routerLink]="['/login']"> Login </a></li>
    <li class="menu_item" *ngIf="currentUser"><a [routerLink]="['/signin']">Logout</a></li>
  </ul>
</div>
</nav>

But the problem is

  • after logged in, that header text is not changing ( not changing login -> logout )
  • after logout, that header text is not changing ( not changing logout -> login )
  • But it change the header text if I refresh the page. But not changing automatically with the route change

Can anyone help me on this ?


Solution

  • You need to let the HeaderComponent know that the authentication status has changed. You could use an observable for this:

    1. introduce isAuthenticated$ observable inside AuthService

    2. inject that service in HeaderComponent, and use the isAuthenticated$ inside the template, with async pipe

    3. when logging in/out, call next() on that observable to trigger changes

    Something like this should do the job:

    class AuthService {
    
        isAuthenticated$ = new BehaviorSubject<boolean>(false);
    
        constructor() {
            const authenticated = !!JSON.parse(localStorage.getItem('currentUser')); 
            this.isAuthenticated$.next(authenticated);
        }
    
        login() {
            this.isAuthenticated$.next(true);
        }
    
        logout() {
            this.isAuthenticated$.next(false);
        }
    
    }
    

    Header component controller:

    class HeaderComponent implements OnInit {
    
      public currentUser: any;
      public isAuthenticated$ = this.auth.isAuthenticated$;
    
      private (private auth: AuthService) {}
    
      ngOnInit() {
        this.isAuthenticated$.subscribe(authenticated => {
          if (authenticated) {
            this.currentUser = JSON.parse(localStorage.getItem('currentUser')); 
          } else {
            this.currentUser = null;
          }
        });
      }
    
    }
    

    Your template:

    <nav class="navbar navbar-default" >
      <div class="collapse navbar-collapse" id="myNavbar">
        <ul class="nav navbar-nav navbar-right">
          <li class="menu_item" *ngIf="!(isAuthenticated$ | async)"><a [routerLink]="['/login']"> Login </a></li>
          <li class="menu_item" *ngIf="(isAuthenticated$ | async) && currentUser.someField === 'someValue'"><a [routerLink]="['/signin']">Logout</a></li>
        </ul>
      </div>
    </nav>