3

I'm trying to create a shared service to communicate between components using an Observable, using: http://blog.angular-university.io/how-to-build-angular2-apps-using-rxjs-observable-data-services-pitfalls-to-avoid/ as a guide:

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


@Injectable()
export class ModalService {

  private _isOpen: BehaviorSubject<boolean> = new BehaviorSubject(false);
  public isOpen: Observable<boolean> = this._isOpen.asObservable();


  openModal() {
    this._isOpen.next(true);
  }

  closeModal() {
    this._isOpen.next(false);
  }

}

in my component(s), I subscribe to isOpen, which receives a value when subscribing:

. . .

  ngOnInit(): void {
    this.subscription = this.modalService.isOpen.subscribe(state => {
      console.log('`isOpen` in subscription', state);
    });
  }

However, when I trigger .openModal() on the shared service instance, the subscriber never receives the new value. What am I doing wrong?

My logic was that by using a Behavior Subject, the subscriber would receive an initial value of false, then I could change the value on click from other components that have an instance of the shared service.

Brandon
  • 29,908
  • 11
  • 86
  • 125
  • next was deprecated, try with this._isOpen.emit(true) – dlcardozo Jan 26 '17 at 03:35
  • TypeScript is telling me: `Property 'emit' does not exist on type BehaviorSubject` – Brandon Jan 26 '17 at 03:42
  • My bad, next it's fine there, it was deprecated on EventEmitter. It seems to be a DI issue, you added the modalService on your main ngModule as a provider right? – dlcardozo Jan 26 '17 at 03:44
  • I don't get it. My use case is identical to: http://stackoverflow.com/questions/36715918/how-to-define-global-variables-in-angular-2-in-a-way-that-i-can-use-them-for-pro and it seems to be working for that user. – Brandon Jan 26 '17 at 03:45
  • If I call: `this.modalService.openModal();` in the component where I subscribe to `isOpen`, it works. If I call the same method from another component with the `modalService` injected into it, and call `.openModal()` it doesn't work. – Brandon Jan 26 '17 at 03:50
  • That's good, you have multiple instances of modalService, you must have only one, check that you only have one provider for modalService, try to provide it only from your app.module.ts – dlcardozo Jan 26 '17 at 03:52
  • I had registered the ModalService as a Provider in a shared module. I moved it to the App module and it works as expected. – Brandon Jan 26 '17 at 03:54

1 Answers1

7

My application has several sub-modules, and a shared module to register common components, and modules between them. I had registered the ModalService in the shared component.

I moved the ModalService to the Providers of the uppermost (app.module.ts) providers array, and it works as expected.

Thanks to @camaron for the tip. Note to self: never, ever register a provider in a shared module :)

Brandon
  • 29,908
  • 11
  • 86
  • 125