Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to filter an Observable array?

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);
 }
like image 506
Fernando Nicolalde Avatar asked Jan 18 '18 16:01

Fernando Nicolalde


2 Answers

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)
    );
}
like image 158
UncleDave Avatar answered Oct 16 '22 11:10

UncleDave


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))
like image 35
Peter Salomonsen Avatar answered Oct 16 '22 11:10

Peter Salomonsen