-2

I am trying to work across modules - I have written a service in a module

sharedService

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

@Injectable({
  providedIn: 'root'
})
export class SharedService {
private paramsSource = new Subject<any>();
current_params$ = this.paramsSource.asObservable();
set_current_params( params:any) {
  this.paramsSource.next(params);
}
get_current_params(){
  console.log(this.current_params$)// returns {'id':'15'} on console
  return this.current_params$
}

I call this from a parallel module where I am able to set current params by using calling the service through the constructor. However, the getter does not seem to work from the same module. The subscription does not seem to work. It seems to return an observable but i am unable to subscribe to it.

my component.ts

import { Component, OnDestroy } from '@angular/core';
import { SharedService } from '../../../core/shared/shared.service';
import { Subscription, Observable } from 'rxjs';



@Component({
  selector: '[app-myComponent]',
  templateUrl: './myComponent.component.html',
  styleUrls: ['./myComponent.component.scss']
})
export class MyComponentComponent implements AfterViewInit {
constructor(
    private shared: SharedService
) { }
ngOnInit() {
  this.shared.set_current_params({'id':'15'});
{
ngAfterViewInit() {
   console.log(this.sharedService.get_current_params());//log line 1
   this.shared.get_current_params().subscribe(current_params => {
   console.log('anything'); //log line 2
   console.log(current_params); //log line 3 
})

}

Log line 1 returns an observable on the first line However, The subscribe returns nothing, and logs 2 and 3 are empty .

I try the same subscription from a different module, the getter also works. Why is it not getting picked up in this component just in the getter?

Venomoustoad
  • 1,203
  • 1
  • 14
  • 38
  • Can you share the complete code of your service and components – Yash Aug 23 '19 at 10:33
  • I have added the complete code of the service/ component involved in this. – Venomoustoad Aug 23 '19 at 10:58
  • 1
    When do you call set_current_params()? If you don't call it, or if you call it *before* MyComponentComponent.ngOnInit is executed, then of course you never receive anything. – JB Nizet Aug 23 '19 at 11:06
  • 1
    If you want to receive the latest value upon subscription, then you may want to make your `paramsSource` a `BehaviorSubject` or a `ReplaySubject` instead of the `Subject` that you have now. With the `Subject` you may have the issue that @JBNizet pointed out. – Sam Herrmann Aug 23 '19 at 11:13
  • I have updated the code. I had actually set it earlier in a different component but for the sake of simplicity, I have included an after view init and put the setter in the ngOnit method and getter after view init. I do see that the getter is working (when i console.log in the getter service method as shown above), I get the params have been set. It is just confusing that I am unable to subscribe to it. – Venomoustoad Aug 23 '19 at 11:27
  • ngAfterViewInit() is called **after** ngOnInit(). you send a message in ngOnInit(), but noone is listening yet, so it's lost. Then, later, you start listening to messages in ngAfterViewInit(), but noone ever sends a message after that, so you don't hear anything. – JB Nizet Aug 23 '19 at 11:30
  • So I should use ReplaySubject and life is set! – Venomoustoad Aug 23 '19 at 11:35

2 Answers2

0

The issue is that you are setting a value before you are subscribing to it. If you move the code from ngOnInit to ngAfterViewInit and move the code from ngAfterViewInit to ngOnInit, then your subscription will work. See StackBlitz example. As mentioned in my comment above, if you need to support the ability to get the latest value upon subscription, i.e. the last value that was emitted before you subscribed, then you need to use either a BehaviorSubject or a ReplaySubject instead of Subject.

Sam Herrmann
  • 6,293
  • 4
  • 31
  • 50
-1
  1. In you share module you will need to add the sharedservice as a Provider.
  2. In you module containing MyComponentComponent you will need to import the SharedModule. You should include the code for the SharedModule and the Module with MyComponentComponent to get a complete answer
Jens Alenius
  • 1,931
  • 2
  • 16
  • 20
  • 2
    This is not quite correct because he has his shared service configured with `providedIn: 'root'`, therefore he does not need to add it to a module as a provider. – Sam Herrmann Aug 23 '19 at 11:06
  • yes that is true. Did not know about that that new decorator. Used only when you want to add providers to the app root. Don't use it to much – Jens Alenius Aug 23 '19 at 11:18