Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

rxjs using combineLatest to filter data stream – stream data is empty when it should not be

I am using combine latest in an angular component to bring together a stream of data with a filter text input:

export class RecordSearchComponent implements OnDestroy {
  @Input() gridData: Observable<TrainingRecord[]> = of([]);

  private filterSubject = new BehaviorSubject<string>('');
  private readonly debounceTimeMs = 300;

  private filterInput$ = this.filterSubject.pipe(
    debounceTime(this.debounceTimeMs),
    distinctUntilChanged(),
  )

  filteredData$ = combineLatest([this.filterInput$, this.gridData]).pipe(
    tap(([filter, data]) => console.log(filter, data)),
    switchMap(([filter, data]) => {
      if (filter === '' || filter === null) {
        return of(data);
      }
      const filterDescriptor = {
        field: 'nameFull',
        operator: 'contains',
        value: filter,
        ignoreCase: true,
      };
      return of(filterBy(data, filterDescriptor));
    })
  );

  ngOnDestroy(): void {
    this.filterSubject.complete();
  }

  onFilter() {
    this.filterSubject.next(this.inputText);
  }
}

The filterSubject is working and I can see the results in the console.

The problem is that the "gridData" value inside combineLatest is always empty. But I can confirm that data is coming in if I subscribe to the gridData on its own in the template. (gridData | async) returns all the records.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

I think if we initialize like this using @Input you might not get the value on initialization, as a safety, you can initialize on ngOnInit.

Also please note: The gridData should have a value when the component is initializing only then it will work!

export class RecordSearchComponent implements OnDestroy {
  @Input() gridData: Observable<TrainingRecord[]> = of([]);

  private filterSubject = new BehaviorSubject<string>('');
  private readonly debounceTimeMs = 300;
  filteredData$!: Observable<TrainingRecord[]> = of([]);

  private filterInput$ = this.filterSubject.pipe(
    debounceTime(this.debounceTimeMs),
    distinctUntilChanged(),
  )

  ngOnInit() {
    this.filteredData$ = combineLatest([this.filterInput$, this.gridData]).pipe(
        tap(([filter, data]) => console.log(filter, data)),
        switchMap(([filter, data]) => {
          if (filter === '' || filter === null) {
            return of(data);
          }
          const filterDescriptor = {
            field: 'nameFull',
            operator: 'contains',
            value: filter,
            ignoreCase: true,
          };
          return of(filterBy(data, filterDescriptor));
        })
      );
  }

  ngOnDestroy(): void {
    this.filterSubject.complete();
  }

  onFilter() {
    this.filterSubject.next(this.inputText);
  }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading