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!

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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?
I got the error to go away by adding a setTimeout() function to the subscription as seen in this answer: 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?
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 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
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.