How to track change of a value emitted in one component in another component in Angular

Viewed 350

Component A shows notifications count. Whereas, Component B gets live count of notificationss which I'm emitting it and subscribing the value in Component A. For some reason, the count gets updated only when I make page transition.

In a gist, here's what I'm doing.

Component B

ngOnInit(){
 this.handleRealTimeCount();
}

handleRealTimeCount() {
  this.countSvc
    .getCount()
    .subscribe((res: any) => {
      this.countSvc.setCount(
        res.count
      );
    });
}

Component A

  this.getUnreadCount();
}

getUnreadCount() {
  this.countSvc.unreadCount.subscribe((res) => {
    this.notificationsCount = res;
  });
}

In my Count Service, I'm using EventEmitter variables like this

export class CountService {
  unreadCount = new EventEmitter();

  setCount(count) {
    this.unreadCount.emit(count);
  }

Could you please let me know how could I get the real time count updated whenever a notification is received.

2 Answers

Can you try with BehaviorSubject rather than EventEmitter

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class CountService  {   
  constructor() { } 
  private paramSource = new BehaviorSubject(0);
  unreadCount = this.paramSource.asObservable();
  setCount(param:number) { this.paramSource.next(param)}    
}

You are almost there. I will suggest using a BehaviourSubject in the service rather than an EventEmitter and also subscribe directly in the template of your components using the async pipe.

The Service

@Injectable({
  providedIn: 'root'
})
export class CountService {
  private _unreadCount$: BehaviourSubject<number> = new BehaviourSubject<number>(0);
  get unreadCount$ ():Observable <number> {
  return this._unreadCount$;
  }

  increaseCount(amount:number) {
  this._unreadCount.pipe(take(1)).subscribe((count: number) => {
  this._unreadCount.next(count + amount);
})

}

Component A

count$: Subject<number> = new Subject<number>();

getUnreadCount() {
  this.countSvc.unreadCount$.subscribe((count) => {
    this.count$.next(count);
  });
}

increase(count: number) {
this.countSvc.increaseCount(count);
}

// Template of Component A

<div *ngIf="count$ | async as count">
You have {{count}} notifications
</div>
<button (click)="increase(1)">Increase</button>

Basically that's it. By following the above approach your components will be synced, just make sure to inject the service and subscribe to the unreadCount$ property

Related