16

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);
 }
2
  • 1
    uh... filter operator doesn't work for you? Commented Jan 18, 2018 at 16:31
  • I tried but i get this error "[ts] Property 'attending' does not exist on type 'any[]'. any" Commented Jan 18, 2018 at 16:40

2 Answers 2

18

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)
    );
}
Sign up to request clarification or add additional context in comments.

Comments

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))

3 Comments

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
Sorry should have imported map on both options and not import pipe on the second. Corrected now.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.