Angular 5: How to broadcast event from authguard to header?

Viewed 706

I am trying to broadcast an event from authguard component to my header component.

Broadcast service

@Injectable()
 export class BroadcastService {

 public subject = new Subject<any>();

 sendMessage(message: string) {
  this.subject.next(message);
 }
}

Receiver (header component)

export class HeaderComponent {
  constructor(public broadcast: BroadcastService) {
    this.broadcast.subject.subscribe(message => {
    alert('broadcast received: ' + message);
   });
 }
}

Broadcast (authguard component -- doesn't work)

export class AuthGuard implements CanActivate {
 constructor(public broadcast: BroadcastService) {      
 }

 canActivate(): boolean {
  this.broadcast.sendMessage('Hi from AuthGuard');
  return true;
 }
}

Broadcast (dashboard component -- works)

export class DashbardComponent {
 constructor(public broadcast: BroadcastService) {      
 }

 ngOnInit() {
  this.broadcast.sendMessage('Hi from AppComponent');
 }
}

app.component.html

<headerComponent></headerComponent>
<router-outlet></router-outlet>

routing

{
 path: 'dashboard',
 component: DashboardComponent,
 canActivate: [AuthGuard]
}

The issue is that when I broadcast from my authguard component, the receiver in my header component never receives the message. I can confirm that the canActivate method in authGuard is called for every path.

But when I broadcast from a page component (eg. dashboard), the receiver in the header component does receive the message.

Does anyone know how to publish a message from the authguard to my header component?

2 Answers

You have to use BehaviorSubject

here's an example

boradcast.service.ts

import { Injectable } from '@angular/core';
import { Subject, BehaviorSubject } from 'rxjs'

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

  constructor() { }

  public subject = new BehaviorSubject<any>('');

  sendMessage(message: string) {
    this.subject.next(message);

  }

}

here is Stackblitz demo

Please use BehaviorSubject instead of Subject

A BehaviorSubject holds one value. When it is subscribed it emits the value immediately. A Subject doesn't hold a value.

Please check this https://stackoverflow.com/a/43351340/2742156

let bSubject = new BehaviorSubject(null); // null or any default value
bSubject.subscribe(value => {
  console.log("Subscription got", value);
});

Subscriber always receives the last emitted value

Updated:

Guard

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private broadcastService: BroadcastService) {}

  canActivate(): boolean {
    console.log('auth guard called');
    this.broadcastService.subject.next('from guard');
    return true;
  }
}

broadcast service

@Injectable()
 export class BroadcastService {

 public subject = new BehaviorSubject<any>('hello');

 sendMessage(message: string) {
  this.subject.next(message);
 }
}

subscriber(header component)

constructor(private broadcastService: BroadcastService) {
broadcastService.subject.subscribe((res) => {
        console.log('Inside login', res);
      });
}

route config

{
    path: 'some route',
    component: SomeComponent,
    canActivate: [AuthGuard]
  }
Related