Sojye
Sojye

Reputation: 175

Angular 2 - Using Observables in a component to emit values to other components

I am wondering if it is possible to use Observables in components, and which other components can subscribe to?

BugListComponent - component is injected in the boot.ts file where I load all my services (where boostrap is located)

import {Subject, BehaviorSubject} from 'rxjs/Rx';

viewBugList$: Subject<boolean>;

constructor() { 
    this.viewBugList$ = new BehaviorSubject<boolean>(false);
}

// Called from template, sends in 'true'
private enableIEview(enable: boolean) {   
    if(enable) {
        this.viewBugList$.next(true);
    }
}

BugListContainerComponent

import {BugListComponent} from '../buglist/bug-list.component';

initView: boolean;

constructor(private _bugListComp: BugListComponent) {
    this.initView = false;
}

ngOnInit() {
    this._bugListComp.viewBugList$.subscribe(e => {
        if(e != null) {
            this.initView = e;
        }
    });
}

So, far the 'subscribe' in the BugListContainerComponent does not seem to be affected when the .next is called from the BugListComponent.

Below is an overview image: The architecture

What am I missing? Thanks!

Upvotes: 1

Views: 3488

Answers (2)

micronyks
micronyks

Reputation: 55443

BugListComponent

import 'rxjs/Rx';
import {Output,EventEmitter} from 'angular2/core';
import {sharedService} from './sharedService';


constructor(private ss:sharedService) { 

}

private enableIEview(enable: boolean) {   
    if(enable) {
        this.ss.setEventEmitter(enable);
    }
}

sharedService.ts

import 'rxjs/Rx';
import {Output,EventEmitter} from 'angular2/core';

export class sharedService {

@Output() viewBugList$:EventEmitter<boolean>=new EventEmitter();

  constructor() { 

  }

  setEventEmitter(enable:boolean) {
    //this.viewBugList$.emit(enable);
      this.viewBugList$.next(enable);
  }

  getEventEmitter()
  {
     return this.viewBugList$;
  }
}

boot.ts

import {sharedService} from './sharedService';
bootstrap(AppComponent, [ SharedService ]);

BugListContainerComponent

import 'rxjs/Rx';
import {Output,EventEmitter} from 'angular2/core';
import {sharedService} from './sharedService';

initView: boolean;

constructor(private ss:shareService) {
    this.initView = false;
}

ngOnInit() {
    this.ss.getEventEmitter.subscribe(e => {
        if(e != null) {
            this.initView = e;
        }
    });
}

Upvotes: 2

Thierry Templier
Thierry Templier

Reputation: 202176

In fact it's not possible. You can only trigger events to the parent component of a component using the EventEmitter class defined as @Ouput of the child component.

For other components, you need to define the Observable within a shared service. The component can inject this service and subscribe on the observable. The other component can also inject the service and trigger the event.

It's almost the same code as yours but in a service service.

  • Shared service

    export class SharedService {
      constructor() { 
        this.viewBugList$ = new BehaviorSubject<boolean>(false);
      }
    
      enableView() {
        this.viewBugList$.next(true);
      }
    }
    
  • Define the service when bootstrapping

    bootstrap(AppComponent, [ SharedService ]);
    
  • BugListContainerComponent

    constructor(private service: SharedService) {
      this.initView = false;
    }
    
    ngOnInit() {
      this.service.viewBugList$.subscribe(e => {
        if(e != null) {
          this.initView = e;
        }
      });
    }
    
  • BugListComponent

    viewBugList$: Subject<boolean>;
    
    constructor(private service:SharedService) { 
      this.viewBugList$ = new BehaviorSubject<boolean>(false);
    }
    
    // Called from template, sends in 'true'
    private enableIEview(enable: boolean) {   
      if(enable) {
        this.service.viewBugList$.next(true);
      }
    }
    

This shared service must be defined when bootstrapping your application in order to have a single instance for the whole application.

Upvotes: 2

Related Questions