0

I am trying to share service to a component, for this, I have created service.ts where the code looks like:

import { Subject } from 'rxjs/Subject';

export class CommonService {
    CommonList = new Subject<any>();
}

Of course, this service is in provider list in app.module.ts Then, I have a component sidebar. From sidebar component i am subscribing this service:

  ngOnInit() {
    this.subscription = this.CommonServicePrivate.CommonList.subscribe(
      (result: any) => {
        console.log(result);
      }
    );
  }

Here is the problem, If I try to add some list in this service from app.component.ts via some method:

  click(){
   this.CommonService.CommonList.next([{"some_key":"some_value"}]);
  }

This actually works, but when i try this:

  ngOnInit(){
    this.CommonService.CommonList.next([{"some_key":"some_value"}]); 
  }

it does not work.

The point is that I want to pass this service to a component on load application.

In case of ngAfterViewInit, when i am trying to render this result to some template, i am getting error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value:

If someone has this experience could you please share to me. Thanks.

mr_e30
  • 3
  • 6
  • i guess you are looking for a router resolve before the component loads you need data in the component right ? – Rahul Singh Aug 01 '17 at 17:10
  • Yeap, because the information about sidebar is coming from Rest API, and i need to load it automatically, but another point is that this sidebar i should load in another component as well so i really do not want to call this API twice, solution is that i will store it in service, and from components i will call this service but problem is as i mentioned: via method it works, but onload - it does not work, sometimes gives me error that : EXCEPTION: Expression has changed after it was checked. – mr_e30 Aug 01 '17 at 17:16

2 Answers2

0

Subject will emit value its subscription when they are subscribe to it. When you're pushing value inside you CommonList from ngOnInit, it does emit value. But the underlying inner component(event subscription) haven't happened yet.

You could fix this issue just by using ngAfterViewInit lifecycle hook, where it ensures that inner Component tree have been initialize(expect content projection). Essentially it will ensure that component subscription have been happened.

ngAfterViewInit(){
  this.CommonService.CommonList.next([{"some_key":"some_value"}]); 
}

Or another way of achieving the same goal would be, use BehaviourSubject inspite of Subject. There difference between these two is BehaviourSubject store & emits its last subscription.

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • Nope, in this case there is another problem, this should be rendered in template so all the time i am getting error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: – mr_e30 Aug 01 '17 at 17:19
  • @mr_e30 did you give try for this? – Pankaj Parkar Aug 02 '17 at 14:08
0

I can suggest a work around for the ExpressionChangedAfterItHasBeenCheckedError.

This is a genuine error as pointed out by gunter here https://stackoverflow.com/a/43375600/2708210

what you can do is make the call inside of a setTimeout i had this issue and this was a work around.

 this.subscription = this.service.spinner$
  .subscribe(item => setTimeout(() => this.showProgress = item, 0)); 

This is a peice of code from my app git link

Rahul Singh
  • 19,030
  • 11
  • 64
  • 86
  • Seems working, but i am little bit wondering about setTimeout, i mean, what will happen if this service takes some time, for example 2 second to get from some api and then load into it? Did you test like this condition? – mr_e30 Aug 01 '17 at 17:52
  • Yes i am using it for firebase scenarios and it works fine so farm my case was every time my component loafsbthe values change to and fro so this was the only way + doesn't hamper aot build – Rahul Singh Aug 01 '17 at 17:55
  • Yeap, i did test as well right now, just made php file with sleep function and called it from angular and it works, man thank you : ) – mr_e30 Aug 01 '17 at 18:21