Angular 2 observable subscription not triggering
The same service instance isn't being shared across your App and Home components because you have listed SidenavService
as a provider for both.
When you define service provider in the providers
entry of a Component decorator, that service is then available to that component and all of its children as a singleton, meaning the same instance of the service will be used.
If you redefine a provider in a child component, it will create a new instance of the service and will no longer share the same service instance as its parent/ancestor.
If you are using SidenavService
in both App and Home components and need the same instance, you should only provide it in the App component and remove it from the providers
entry of Home.
For more information on DI, have a read of the following links:https://angular.io/docs/ts/latest/guide/dependency-injection.htmlhttps://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html
The issue is that contrary to other frameworks Angular doesn't seem to force Service
s to be singletons by default.
Thus what you encounter is a situation when you declared each Component
of yours to have its own instance of the Service
. This results in each instance having different attributes (toggle
and toggleObs
). Schematically:
App -> SidenavService [instance A]
Home -> SidenavService [instance B]
You need to change your declarations to match Singleton Services as described in Angular Documentation. Which results in sharing only a single instance of a Service
among all Components
. Schematically:
App -> SidenavService [instance A]
Home -> SidenavService [instance A]
I think the issue is your Subject
type With Subject
, any component that subscribes after an event has fired will NOT receive a value. To replay the previous value to late subscribers use BehaviorSubject
or ReplaySubject
instead of Subject
.
More on different Subject types from http://reactivex.io/documentation/subject.html
Behavior Subject
When an observer subscribes to a BehaviorSubject, it begins by emitting the item most recently emitted by the source Observable (or a seed/default value if none has yet been emitted) and then continues to emit any other items emitted later by the source Observable(s).
ReplaySubject
ReplaySubject emits to any observer all of the items that were emitted by the source Observable(s), regardless of when the observer subscribes.
A BehaviorSubject
does require a default value when setting it up. So you'd need to create it with some sort of value:
updateIBOsNavigationSubject = new BehaviorSubject<any>('');updateIBOsNavigation$ = this.updateIBOsNavigationSubject.asObservable();updateIBOsNavigation(navigationData) { log.d('updateIBOsNavigation', JSON.stringify(navigationData)); this.updateIBOsNavigationSubject.next(navigationData);}
A ReplaySubject
does not require a default value.
EDIT
When using a shared service it is also important to make sure the service is being provided ONLY at the root module. If it is provided multiple places, then the components may not be getting the same instance. Even if the service is provided at the root level, if a module between the root level and your component provides the service, a new instance will get sent down that branch of the Dependency Injection tree.
Hope this helps.