2017-07-03 8 views
1

私は、繰り返し繰り返される要素をフィルタリングするフィルタリングソリューションを探しています。私は答えの中にある基本的なパイプソリューションを持っていますhereフィルタにラジオボタンを使用したAngular2フィルタ/パイプ

<input [(ngModel)]='query'/>は、同じコンポーネント内にある場合にのみ機能します。

しかし、フィルタリングされたラジオボタンから別のコンポーネント内のフィルタ値を取得する必要があります。

ここまでは私のコードです。

filter.component

<div class="topic" *ngFor="let topic of topics"> 
    {{topic.term}} 
    <input [(ngModel)]="query" type="radio" name="topicFilter" [value]="topic.term"/> 
</div> 

grid.component

<router-outlet></router-outlet> // this pulls in the filter.component 

<input [(ngModel)]="query"> // this is a text input that works as wanted (for showing what I'm wanting to achieve) 

<grid-item *ngFor="let user of users | topicFilterPipe: 'topic':query"> 
    <a [routerLink]="['user-story', user.uid]"> 
    <h1>{{user.fname}}</h1> 
    </a> 
    {{user.topic}} 
</grid-item> 

filter.pipe

import { Pipe, PipeTransform } from '@angular/core'; 

@Pipe({ 
    name: 'topicFilterPipe' 
}) 
export class TopicFilterPipePipe implements PipeTransform { 

    public transform(value: Array<any>, keys: string, term: string) { 
    console.log('pipe has run'); 
    if (!term) return value; 
    return (value || []).filter((item) => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key]))); 

    } 

} 

BASICA lly - テキスト入力と同じメソッドを実装しようとしましたが、選択したラジオはfilter.componentの範囲内です。しかし、私は選択された値をパイプ&に渡してから、ngModelを使ってフィルタリングするのに苦労しています。ありがとうございました!

注:私は

+0

あなたのデータの数行よりも多くを持っている場合は、フィルタリングのためのパイプを使用するために、通常は良いアイデアではありません。これを参照してください:https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe 代わりにコンポーネント自体をフィルタリングすることができます。 – DeborahK

+0

@DeborahK私は少なくとも500行のデータを持っています。あなたはおそらく正しいでしょう。 filter.componentでフィルタリングを処理し、grid.componentに渡すにはどうすればいいですか? – Minum

+0

以下の答えで私の回答を見てください。 – DeborahK

答えて

1

あなたの問題は、コンポーネント間の通信についてです別々のコンポーネントに残っている必要がありますangular2 +フィルタ部品に非常に新しいです。 FilterComponentは、新しいクエリが更新されることをGridComponentに通知する必要があります。

ServiceはAngularのシングルトンです(例外は存在しますが、ここでは関係ありません)。サービス内のデータをあるコンポーネントから設定すると、他のコンポーネントがデータにアクセスできます。 BehaviorSubjectを使用して情報を格納することによってObserverパターンを使用しています。

QueryService:

このサービスにはクエリデータがあります。 getQueryは、任意の構成要素によって聴くことができる観測可能性を与える。

@Injectable() 
export class QueryService{ 

    public query = new BehaviorSubject<string>(''); 

    public getQuery(){ 
     return query; 
    } 

    public setQuery(queryStr){ 
     this.query.next(queryStr); 
    } 
} 

FilterComponent

FilterComponentがサービスおよび更新値の変化を呼び出します。

HTML

<input 
    [ngModel]="query" 
    (ngModelChange)="updateQuery($event)" 
    type="radio" 
    name="topicFilter" [value]="topic.term"/> 

TS

constructor(private queryService: QueryService){} 
public updateQuery(query){ 
    queryService.setQuery(query); 
} 

GridComponent

public query:string; 

constructor(private queryService: QueryService){} 

ngOnInit(){ 
    // .... other code 
    queryService.getQuery() 
    .subscribe(queryVal => { 
      this.query = queryVal; 
    }); 

} 

OR

あなたは角度のイベントを使用することができますグリッドコンポーネントがイベントを捕捉して新しいクエリを取得できるように、イベントをトリガします。しかし、サービスのやり方はより良いです。あなたはルータの内部にFilterComponentを持っているので、ここでイベントメカニズムを使用するのは難しいです。

どちらの場合でも、質問に記載されているようにパイプを使用することができます。

import { Pipe, PipeTransform } from '@angular/core'; 

@Pipe({ 
    name: 'topicFilterPipe' 
}) 
export class TopicFilterPipePipe implements PipeTransform { 

    public transform(value: Array<any>, keys: string, term: string) { 
    console.log('pipe has run'); 
    if (!term) return value; 
    return (value || []).filter((item) => keys.split(',').some(key => item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key]))); 

    } 

} 

質問に記載されているパイプを使用するか、コンポーネントのリストを直接フィルタリングすることができます。

まだ問題がある場合は、plnkrを作成してください。私はこの回答であなたを更新できます。あなたはこのような方法でサービスを構築することができ

+0

申し訳ありません - 私は私が完全に確信していません。私はangular2と非常に初心者です。もう少し明確になりますか? – Minum

+0

もちろん、どうしてですか?私は1時間後に答えをより詳細に更新します。今旅行中です。 – Skeptor

+0

@Minumが更新されました。 – Skeptor

0

performFilter(filterBy: string): IProduct[] { 
    filterBy = filterBy.toLocaleLowerCase(); 
    return this.products.filter((product: IProduct) => 
      product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1); 
} 

これは、製品のリストをフィルタリングしている...しかし、あなたは何が必要フィルタリングするために、それを調整できます。これはサービス内にある必要があるので、共有することができるので、フィルタリングするリストを渡す必要があります。だから、もっとこのように:

performFilter(products: IProduct[], filterBy: string): IProduct[] { 
    filterBy = filterBy.toLocaleLowerCase(); 
    return products.filter((product: IProduct) => 
      product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1); 
} 
+0

私はこれを私のコードにどのように実装するのかが完全にはわかりません。私はAPIからあなたの "製品"を収集するために使っているのと同じ方法に従っていないので、私は自分のコードに実装する方法をかなり理解できません。私は角度の非常に初心者です – Minum

+0

サンプルコードの一部でプランナーを構築できる場合は、より詳細な例を提供することができます。 Plunkerを使用して、このリンクを使用してAngular appのサンプルを作成することができます:https://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue – DeborahK

関連する問題