2017-07-03 75 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進行過濾。謝謝!

注:我很新的angular2 +過濾器組件必須保持在一個單獨的組件

+0

它通常不是,如果你有比數據的幾行更多地使用管道用於過濾一個好主意。看到這個:https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe 你可以改爲過濾組件本身。 – DeborahK

+0

@DeborahK我至少有500行數據。所以你可能是正確的。我將如何處理filter.component中的過濾並將其傳遞到grid.component中 – Minum

+0

請參閱下面的答案中的回覆。 – DeborahK

回答

1

您的問題是有關組件之間的通信。 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

您可以使用角事件機制並觸發一個事件,以便gridcomponent可以捕獲該事件並獲取新查詢。但服務方式更好。由於你在路由器中有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

當然,爲什麼不呢。我會在一小時後更詳細地更新答案。現在旅行。 – 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,我們可以提供一個更詳細的例子。您可以使用Plunker使用以下鏈接構建示例Angular應用程序:https://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue – DeborahK