1

I want to keep total amount of my component updated as it's changing, and I'm wondering is this right:

I have a shared.service.ts which is injected into my component so it looks like this (my shared service):

shared.service.ts

private sumEmit= new BehaviorSubject<number>(0);

public updateValues() {
this.sum= 0;
this.sum+= +(price*quant).toFixed(2);
this.sumEmit.next(this.sum);
}

Method to get total amount also in service:

 getTotal(): BehaviorSubject<number> {
    return this.sumEmit;
  }

So, every time updateValues() method is called, it will emit value of sum, that's right?

And in my component which need to retreive value everytime value is changed I did this:

mycomponent.component.ts

First of all I injected shared service, after that in ngOnInit life cycle hool I wrote:

// simple variable to hold value from service

total : number;


ngOnInit() 
{
    this.total = this.SharedService.getTotal();
}

Does this mean that my value will be up to date everytime total amount is changed?

Most confusing part for me is that I called this method only once in a ngOnInit which is rendered when component is opened, but value is kept updated.. Could anyone explain me this please? How come variable in my component is aware when value is changed in service? Which part is responsible for that?

Thanks

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
Roxy'Pro
  • 4,216
  • 9
  • 40
  • 102
  • Where do you use `total` property? – yurzui Oct 24 '18 at 19:38
  • @yurzui I use it on one of my components to display current value of total amount, there is an array in shared service and everytime I add value or someone else in that array I'm calling method updateValues which emits total and I display it on few of components whenever I need it.. – Roxy'Pro Oct 24 '18 at 19:56
  • Are you using it like `{{total}}` or `{{total | async}}`? – yurzui Oct 24 '18 at 20:02
  • @Roxy'Pro I updated my answer with some of the question you asked in comments. I hope it's clearer now. Let me know if there is something you do not understand :) – lealceldeiro Oct 25 '18 at 13:07

2 Answers2

1

How come variable in my component is aware when value is changed in service?

You are using BehaviourSubject, This means that new subscribers will always get the last value emitted synchronously.

Which part is responsible for that?

this.sumEmit.next(this.sum);

Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • @Sajeetharan why it works if I don't use .subscribe in my component, anyway component know for new value, how ? – Roxy'Pro Oct 24 '18 at 19:20
  • @Roxy'Pro that is the functionality of using behavioursubject. it is handled within the core itsef. if you return observable only you need to subscribe, since you are returning a subject this should work – Sajeetharan Oct 24 '18 at 19:22
  • if you want to subscribe in your component return return this.sumEmit; an observable and call subscribe() – Sajeetharan Oct 24 '18 at 19:22
  • @Sajeetharan Thanks for help, so if I want to subsribe i can change BehaviorSubject to Observable ? What is better, what you think? – Roxy'Pro Oct 24 '18 at 19:24
  • you should use observable here as i see and understand the difference betwen the two from here https://stackoverflow.com/questions/39494058/behaviorsubject-vs-observable – Sajeetharan Oct 24 '18 at 19:25
1

So, every time updateValues() method is called, it will emit value of sum, that's right?

Yes, that's right.

Does this mean that my value will be up to date every time total amount is changed?

Yes.

How come variable in my component is aware when value is changed in service?

Because BehaviorSubject extends from Subject which extends from Observable (and implements SubscriptionLike). Observables work in a way that every time a new value is set to the variable by the publishers (this.sumEmit.next(this.sum) in this case) all subscribers are notified with the new value.

You can read more about this at Angular-Observables and ReactiveX-Observable

Which part is responsible for that?

This one

this.sumEmit.next(this.sum);

Additional notes

  • Why it works if we do not use .subscribe?

Because the value property can be accessed at any time, a distinctive characteristic of BehaviorSubjects (see this discussion). This is different from Subject or Observable, where you start getting values only if you subscribe to their streams.

We can access the value using the getValue method, i.e.: let theValue = this.SharedService.getTotal().getValue(). Also, if we assign the BehaviorSubject to a variable (let's call it val) and use this variable, i.e. with the async pipe, the value is automatically extracted by this pipe and you'll see the UI updated automatically, without needing to subscribe to the stream (the pipe does this for you). For example:

// component.ts
this.val = this.SharedService.getTotal(); // val is a `BehaviorSubject`

// component.html
{{ val | async }}
  • If I want to subscribe can I change BehaviorSubject to Observable?

You don't need to change to Observable in order to subscribe. You can subscribe to BehaviorSubject as well, in the same way you would do with an Observable. In case you want to get the BehaviorSubject as Observable you just need to do: const myObservable: Observable = myBehaviorSubject.asObservable();

  • Which one is better: BehaviorSubject or Observable?

We can not say one is better than the other, they just behave differently in some aspects. You need to apply one or the other depending on the situation. In general, BehaviorSubjects are useful for representing "values over time". For instance, an event stream of birthdays is a Subject, but the stream of a person's age would be a BehaviorSubject (See BehaviorSubject section at RxJS-Overview).

Further readings

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80