0

Good afternoon,

I'm trying to update my component to display the correct value of a service variable when it changes. I currently have this:

Component1 HTML

{{icons | json}}

Component1

icons: {
  icon1: boolean,
  icon2: boolean,
}

constructor(private _service: Service1) {
  this.icons = this._service.navIcons;
}

Component2

constructor(private _service: Service1) {
  this._service.signIn();
}

Service1

navIcons: {
  icon1: false,
  icon2: false
}

navIconsChange: Subject<any> = new Subject<any>();

constructor() { 
  this.navIconsChange.subscribe((value) => { this.navIcons = value; console.log(value) });
}

resetIcons() {
  this.navIconsChange.next(
    this.navIcons = {
       icon1: false,
       icon2: false
    });
}

signIn() {
  this.navIconsChange.next(
    this.navIcons = {
       icon1: true,
       icon2: true
    });
}

The idea is that when the signIn() method is called from Component2, the navIcons should update and those updates should display on Component1. The console.log I have in the subscribe logs that this change took place, however, the icons in Component1 HTML never update. I would assume these should automatically update since the icons are getting updated in Component1's constructor from Service1. How can I get these variables to update when Component2 calls the signIn() method?

This is all based off of this answer: https://stackoverflow.com/a/43161506/4927000

Thank you!

Naman Kheterpal
  • 1,610
  • 1
  • 7
  • 16
Josh
  • 384
  • 1
  • 4
  • 17

1 Answers1

1

You need to modify much of your code as you are doing many things wrong way.

Component 1

icons: {
  icon1: boolean,
  icon2: boolean,
}

constructor(private _service: Service1) {
    this._service.navIconsChange.subscribe((value) => {
     this.navIcons = value; 
     console.log(value) 
    });
}

Service 1

navIcons: {
  icon1: false,
  icon2: false
}

navIconsChange: Subject<any> = new Subject<any>();

resetIcons() {
  this.navIconsChange.next({
       icon1: false,
       icon2: false
    });
}

signIn() {
  this.navIconsChange.next({
       icon1: true,
       icon2: true
    });
}

Component 2 and Component1 HTML will remain same.

This way your comopnent 1 will know when ever value gets changed.

Also if you want to cache the result in service for other component you can manually assign it to variable after .next or use BehaviourSubject like:

Service 1

navIcons = {
  icon1: false,
  icon2: false
}

navIconsChange: Subject<any> = new BehaviourSubject<any>(navIcons);

Add comments if you need further help.

Naman Kheterpal
  • 1,610
  • 1
  • 7
  • 16
  • This seems to be on the right track, however the subscription seems to take a while to execute. Also, I'm getting the following error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'. I was getting this error previous when calling the service directly from the HTML so I wanted to change it. Any ideas as to why this would be happening? – Josh Mar 28 '18 at 14:45
  • I got the error to go away by adding a setTimeout() function to the subscription as seen in this answer: https://stackoverflow.com/a/45444242/4927000. Everything is working fast and how I would expect, but I can't help but think this is a poor way to execute. Thoughts? – Josh Mar 28 '18 at 14:54
  • Nevermind, I realized I was changing these values in ngOnInit(), not the constructor so it sounds like the changes were made before Change Detection took place. Thanks so much for your help! – Josh Mar 28 '18 at 15:01
  • @Josh I hope everything is working fine for u. But don't use `setTimeout` in your code may be you can post the complete error or code to help under stand the issue. @acdcjunior i am so amazed to see that you such great learning attitude and take feedback positively. I would try to copy that too. :D – Naman Kheterpal Mar 29 '18 at 07:33
  • Yes, everything is working great without using setTimeout. I had a feeling that wasn't a great option. :) Thanks again for your help, I was able to fix the ExpressionChangedAfterItHasBeenCheckedError by moving my code into the constructor instead of the ngOnInit. – Josh Mar 29 '18 at 15:03