how to filter an Observable array?

18,144

Solution 1

You should be able to use the map and the filter operators for this, combined with Array.prototype.filter. If I've understood your data correctly it should be something like this:

import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';

userEvents: Observable<any[]>;

constructor(public auth: AuthService, private upSvc: FilesServiceService) { 
  this.userEvents = this.upSvc.getUserEvents(this.auth.currentUserId)
    .map(items => items.filter(item => item.attending))
    .filter(items => items && items.length > 0);
}

First we filter the array down to only items where attending is true. Then we filter out any empty or null arrays.

Updated for RXJS 6:

import { pipe } from 'rxjs'; 
import { map, filter } from 'rxjs/operators';

userEvents: Observable<any[]>;

constructor(public auth: AuthService, private upSvc: FilesServiceService) { 
  this.userEvents = this.upSvc.getUserEvents(this.auth.currentUserId)
    .pipe(
      map(items => items.filter(item => item.attending)),
      filter(items => items && items.length > 0)
    );
}

Solution 2

You cannot use the rxjs filter method for this, but rather the filter method on the array object that you receive from the observable.

So if you have an Observable<any[]> you would filter it like this:

import 'rxjs/add/operator/map';

this.userEvents.map( arr =>
           arr.filter( r => r.attending === true )
     )
     .subscribe( results => console.log('Filtered results:', results))

From rxjs 5.5 you should use .pipe instead of .map directly on the Observable:

 import { map } from 'rxjs/operators';

 this.userEvents.pipe( 
         map(arr =>
           arr.filter( r => r.attending === true )
         )
     )
     .subscribe( results => console.log('Filtered results:', results))
Share:
18,144
Fernando Nicolalde
Author by

Fernando Nicolalde

Updated on June 04, 2022

Comments

  • Fernando Nicolalde
    Fernando Nicolalde about 2 years

    enter image description here

    My method returns an Observable array from Firebase. I have decided to filter the data in the client rather than in the server. My problem is that I want to get only the data if the attribute "attending = true". Any help or other approach is highly appreciated. Thank you very much.

    The method below get the data from the firebase real-time database

    userEvents: Observable<any[]>;
    
    getUserEvents(uid: string) {
    this.userEvents = this.db.list(this.basePatheventsSaved, ref=> 
     ref.orderByChild('uid').equalTo(uid)).snapshotChanges().map((actions) => {
      return actions.map((a) => {
        const data = a.payload.val();
        const $key = a.payload.key;
        return { $key, ...data };
      });
    });
    return this.userEvents;
    } 
    

    The code below is used to fecth the data to be used in the templaTe:

     userEvents: Observable<any[]>;
     constructor(public auth: AuthService, private upSvc: FilesServiceService) { 
    this.userEvents = this.upSvc.getUserEvents(this.auth.currentUserId);
     }
    
  • Fernando Nicolalde
    Fernando Nicolalde over 6 years
    When applying the first option at runtime I get the error map is undefined, and the in the second one "pipe" has not exported member. The problem is solved though. Thank you very much for your help
  • Peter Salomonsen
    Peter Salomonsen over 6 years
    Sorry should have imported map on both options and not import pipe on the second. Corrected now.
  • TomerBu
    TomerBu almost 5 years
    Consider changing the following sentence: "You cannot use the rxjs filter method for this" IMO You should also use the rxjs filter method to filter out any empty or null arrays.