18

New to Angular 2. I'm working on broadcast a event between same level component. Currently I know EventEmitter just can transfer a event to upper level component.

I have checked this this link and know observable may be a way to solve my problem, but the sample in that url seems not work for me.

Does anyone know how to use it(observable) for broadcast event or some other way to transfer event to same level components?

Community
  • 1
  • 1
Garry
  • 1,177
  • 3
  • 14
  • 22

2 Answers2

27

You just need to create some service that will emit messages on which you can subscribe. It can be Observable from rxjs, EventEmitter from node.js, or anything else that follows Observable pattern. Then you should use Dependency Injection to inject this service into concrete components. See this plunker.

class Broadcaster extends EventEmitter {}

@Component({
  selector: 'comp1',
  template: '<div>Generated number: {{ generatedNumber }}</div>',
})
class Comp1 {
  generatedNumber: number = 0;

  constructor(broadcaster: Broadcaster) {
    setInterval(() => {
      broadcaster.next(this.generatedNumber = Math.random());
    },1000);
  }
}

@Component({
  selector: 'comp2',
  template: '<div>Received number: {{ receivedNumber }}</div>',
})
class Comp2 {
  receivedNumber: number = 0;

  constructor(broadcaster: Broadcaster) {
    broadcaster.observer({
      next: generatedNumber => this.receivedNumber = generatedNumber
    });
  }
}

@Component({
  selector: 'app',
  viewProviders: [Broadcaster],
  directives: [Comp1, Comp2],
  template: `
    <comp1></comp1>
    <comp2></comp2>
  `
})
export class App {}

PS In this example I use EventEmitter from angular2, but again, it can be whatever you want

alexpods
  • 47,475
  • 10
  • 100
  • 94
  • 1
    Thanks for responding and clarifying the concept "Observable pattern". – Garry Oct 27 '15 at 01:22
  • 5
    The latest version of angular Emitter has changed to use observables `broadcaster.subscribe(generatedNumber => this.receivedNumber = generatedNumber);` – screenm0nkey Dec 01 '15 at 13:29
  • 1
    Could you please update this answer for modern Angular 2? I think I'm close, but my component2 isn't catching the event, even after updating to use subscribe. – dennis.sheppard Mar 09 '16 at 15:17
16

Use BehaviorSubject

Service:

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

@Injectable()
export class MyService {

   public mySubject: BehaviorSubject<number> = new BehaviorSubject<number>(0);


   public doSomething(): void { 
      let myValue: number = 123;
      this.mySubject.next(myValue);
   }
}

Component:

@Component({ 
  selector: 'app-my-component',
  templateUrl: './my-component.component.html',
  styleUrls: ['./my-component.component.css']
})
export class MyComponent {

   constructor(private myService: MyService) { 
        this.myService.mySubject.subscribe(
             value => {
                console.log(value); 
             }
        );
   }

}
httpete
  • 2,765
  • 26
  • 34
Tomas Marik
  • 4,053
  • 3
  • 31
  • 62
  • I used this approach to get an Angular Materials Toolbar click event to open and close an Angular Materials Sidenav component - Cheers – user1694873 Mar 04 '17 at 14:19