Search code examples
angularrxjsrxjs6

Updation to subject is not happening in Rxjs


I'm trying to update an RxJS Subject via a component's method . But it is not happening properly .

cricketData$ = new Subject<string>();

ngOnChanges() {
  this.cricketData$
    .asObservable()
    .pipe(
      tap(() =>
        console.log(
          'Triggering REST call for cricket tab with the year ',
          this.year
        )
      ),
      take(1)
    )
    .subscribe();
  this.cricketData$.next('sachin');
}

updateCricketData() {
   this.cricketData$.next('dravid');
}

If I remove the take operator , subject is updated . But multiple service calls are triggered while selecting the values from dropdown . Is there any other operator / approach in RxJS using which I can achieve the below scenarios?

  1. service calls are triggered only once while selecting the values from dropdown
  2. subject is also updated via component's method

Please refer the below StackBlitz link . Thanks in advance .

Editor URL Stackblitz: EditorURL

App URL Stackblitz: AppURL


Solution

  • There are two issues.
    First: ngOnChanges triggers multiple times, and every time you change the value you are adding a new pipe working parallelly. take(1) makes your previous pipe stop and only the recent pipe tab is triggered.

    ngOnInit(): void { // runs once
        this.cricketData$
          .asObservable()
          .pipe( // runs on every next
            tap(() =>
              console.log(
                'Triggering REST call for cricket tab with the year ',
                this.year
              )
            )
          )
          .subscribe();
      }
    
      ngOnChanges() {
        this.cricketData$.next('sachin'); // runs on every event on the page
      }
    

    Second issue: Do you really want to trigger this function on ngChange whenever there's an update on the page rather than just the dropdown, if the answer is only when there is a change in the dropdown then you can use a combination of Input set year(value: string)

    example

        export class CricketComponent implements OnChanges {
      private _selectedYear: string;
    
      @Input() set year(value: string) {
        this._selectedYear = value;
        this.cricketData$.next('sachin'); // will trigger with every drop down change
      }
    
      cricketData$ = new Subject<string>();
    
      constructor() {}
    
      ngOnInit(): void {
        this.cricketData$
          .asObservable()
          .pipe(
            tap((value) =>
              console.log(
                'Triggering REST call for cricket tab with the year ',
                this._selectedYear,
                value
              )
            )
          )
          .subscribe();
      }
    
      ngOnChanges() {}
    
      updateCricketData() {
        this.cricketData$.next('dravid');
      }
    }