Search code examples
javascriptangularangular2-services

Broadcast data to multiple unrelated components in Angular2 through single service


I have two unrelated components which uses a single @injectable service.

When specific service method is called. It emits an even. Second components has subscribed that event.

my code is as follow:

Component Bot2:

import { Component, OnInit, NgZone, EventEmitter} from '@angular/core';
import { SpeechEngine} from '../../services/common/Speechengine';

@Component({
  selector: 'bot2',
  template: '<h3>bot2</h3> <input type="button" value="Emmit" (click)="testEmmiter()"/>',
  providers: [],

 })
 export class Bot2 {
   _speechEngine: any
   constructor(private zone: NgZone) {
    this._speechEngine = new SpeechEngine(this.zone);
    this._speechEngine.BotActivation$.subscribe(obj => { this.AutoBotActivation(obj.speechActive) })
 }
 testEmmiter() {
    this._speechEngine.testEmiter();
 }
 AutoBotActivation(speechActive) {
    alert(" Bot2 subscribed function called.")
 }
}

@Component({
  selector: 'bot3',
  template: '<h3>bot3</h3> <input type="button" value="Emmit" (click)="testEmmiter()"/>',
  providers: [],

})
export class Bot3 {
   _speechEngine: any
   constructor(private zone: NgZone) {
     this._speechEngine = new SpeechEngine(this.zone);
     this._speechEngine.BotActivation$.subscribe(obj => { this.AutoBotActivation(obj.speechActive) })
 }
 testEmmiter() {
    this._speechEngine.testEmiter();
 }
 AutoBotActivation(speechActive) {
    alert(" Bot3 subscribed function called.")
 }
}

Service:

@Injectable()
export class SpeechEngine{
  BotActivation$: EventEmitter<any> = new EventEmitter<any>()    
  constructor(private zone: NgZone) {  }
  testEmiter() {
    this.BotActivation$.next({
        speechActive: false
    });
  }

}   

my service is added at appModule Providers. providers: [SpeechEngine]

Problem is when i invoke testEmmiter() from bot2, service emits function and subscription in bot2 catches it. but bot3 is not catching. and voice versa with bot3.

if i am using emitter wrongly, Can someone suggest how to get this functionality. my components are not in any (parent/child) relation. one can be sibling of grand grand grand parent of other.


Solution

  • First create a global publish subscribe Service

    import { Injectable, EventEmitter } from '@angular/core';
    
    @Injectable()
    export class PubSubService {
      emitter: EventEmitter<any> = new EventEmitter();
    
      constructor( ) { }
    
      subscribe(callback) {
        return this.emitter.subscribe(callback);
      }
    
      publish(event, data?) {
        let payload = {
          type: event,
          data: data
        };
        this.emitter.emit(payload);
      }
    
    }
    

    Subscribe in your component(any component)

    constructor( private pubSubService: PubSubService) { }
    
    ngOnInit() {
      this.pubSubService.subscribe(event => {
        if (event.type === 'event_1') {
          // do something
        } else if (event.type === 'event_2') {
          // do something
        }
      });
    }
    

    Publish event from service/component

    this.pubSubService.publish('event_1', "what ever message");