2016-09-17 4 views
9

AngularFire2をAngular Webアプリケーション内で使用しています。 Firebaseのクエリの制限により、必要なデータを正確に提供するクエリを作成することはできません(少なくとも、自分のスキーマを大幅に変更する必要はありません)。クライアント側でFirebaseListObservableをフィルタリングする方法は?

したがって、JavaScript(typescript)内にクライアント側のフィルタ条件を追加したいと考えています。これはどうすればいいですか?私は何らかの形でオブザーバブルにフィルタ関数を追加できますか?以下は、私が何をしているかを示す断片です。

コンポーネントのHTMLテンプレートには、以下のようなものがあります。 htmlフラグメントの "jobs"変数は、FirebaseListObservableです。

<tr *ngFor="let job of jobs | async"> 
    .. fill in the table rows 

コンポーネントのコードは次のようになります。私は、ローカル(クライアント側)を適用することができるように、「this.jobs」フィルタのフィルタ部品を適用する方法は

// in the member declaration of the class 
    jobs : FirebaseListObservable<Job[]>; 

    ... 
    // Notice in ngOnInit(), I'm filtering the jobs list using the the 
    // Firebase criteria. But I want to filter on an additional field. 
    // Firebase allows only single field criteria, so I'm looking for 
    // a way to apply an additional client-side filter to jobs to eliminate 
    // some additional records. 

    ngOnInit(){ 
     this.jobs = this.af.database.list("/jobs/", {query: {orderByChild : "companyKey", equalTo:someKey}}) 
    } 

ありますか?

答えて

7

同じ問題が発生しました。見つからなかった部分は、配列自体(Job[])をフィルタリングし、周囲のObservableラッパー(FirebaseListObservable<Job[]>)ではフィルタリングしませんでした。

これはRxJSオペレータmapを使用して実行できました。

import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/operator/map' 

... 

@Component({ 
    ... 
}) 
export class JobComponent { 

    ... 

    getJobsLessThanPrice(price: number): Observable<Job[]> { 
    return this.af.database.list('jobs', {query: {...}}) 
     .map(_jobs => _jobs.filter(job => job.price > price)); 

    } 
} 

job.price > priceがtrueを返す場合は、それが含まれます。

はまた、私は観察可能なタイプが Job[]Jobあるべきと思っているだろう、あなたの jobsプロパティはタイプ FirebaseListObservable<Job>のに気づきました。

+0

はい、あなたは正しいです。私は私の例を修正しました。優れた答えをありがとう。 –

2

実際に観測可能な部分をフィルタリングする方法は見つけられませんでしたが、場合によっては回避策が見つかりました。 * ngForで要素の疑似フィルタを行うことができます。

// in the member declaration of the class 
    jobs : FirebaseListObservable<Job[]>; 

    ... 

    ngOnInit(){ 
     this.jobs = this.af.database.list("/jobs/", {query: {orderByChild : "companyKey", equalTo:someKey}}) 
    } 

    filter(job : Job) : boolean{ 
    // Return true if don't want this job in the results. 
    // e.g. lets filter jobs with price < 25; 
    if (job.price < 25){ 
     return true; 
    } 
    return false; 
    } 

私はまだ実際に観測可能にフィルタリングする方法を探していますが、当面のために:だから私の例では

<tr *ngFor="let job of jobs | async" [hidden]="filter(job)"> 
    .. fill in the table rows 

が追加我々はコンポーネントコードにフィルタ()メソッドを追加するなりこの回避策は使用できます。

+0

私はそこだと思いますObservablesのプリミティブを使ってこれを行うより良い方法です。誰かが例を持っていますか? –

0

あなたは、コンポーネントのテンプレートで、このパイプを使用し、独自のパイプ(角1.X上フィルターに類似)

import {Pipe, PipeTransform} from '@angular/core'; 
import * as _ from 'lodash'; 

@Pipe({ 
    name: 'search' 
}) 
export class SearchPipe implements PipeTransform { 

transform(value: any, args?: any): any { 

    if (args) { 
    return _.filter(value, d => _.find(_.valuesIn(d), v => 
     _.toLower(v).indexOf(_.toLower(args)) !== -1)); 
    } 

return value; 
} 
} 

を書き込むことができます。

<input [(ngModel)]="term"> 
<li *ngFor="let item of items | async | search:term">{{item}}</li> 
関連する問題