15

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);
 }
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Fernando Nicolalde
  • 187
  • 1
  • 2
  • 12

2 Answers2

17

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)
    );
}
Community
  • 1
  • 1
UncleDave
  • 6,872
  • 1
  • 26
  • 44
13

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))
Peter Salomonsen
  • 5,525
  • 2
  • 24
  • 38
  • 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 – Fernando Nicolalde Jan 18 '18 at 17:15
  • Sorry should have imported map on both options and not import pipe on the second. Corrected now. – Peter Salomonsen Jan 18 '18 at 18:26
  • 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. – TomerBu Jul 31 '19 at 19:31