2016-11-19 37 views
7

我需要通過更改下拉列表中的類別來過濾ngFor循環內的項目。因此,當從列表中選擇特定類別時,應只列出包含該類別的項目。如何根據對象屬性過濾「ngFor」循環內的項目字符串

HTML模板:

<select> 
    <option *ngFor="let model of models">{{model.category}}</option> 
</select> 

<ul class="models"> 
    <li *ngFor="let model of models" (click)="gotoDetail(model)"> 
    <img [src]="model.image"/> 
    {{model.name}},{{model.category}} 
    </li> 
</ul> 

項目數組:

export var MODELS: Model[] = [ 
{ id: 1, 
    name: 'Model 1', 
    image: 'img1', 
    category: 'Cat1', 
}, 

{ id: 2, 
    name: 'Model 2', 
    image: 'img2', 
    category: 'Cat3', 
}, 

{ id: 3, 
    name: 'Model 3', 
    image: 'img3', 
    category: 'Cat1', 
}, 
{ id: 4, 
    name: 'Model 4', 
    image: 'img4', 
    category: 'Cat4', 
}, 

... 
]; 

而且,在下拉列表中包含重複的類別名稱。它只需要列出唯一的類別(字符串)。

我知道創建一個自定義管道是正確的方式來做到這一點,但我不知道如何寫一個。

Plunker:http://plnkr.co/edit/tpl:2GZg5pLaPWKrsD2JRted?p=preview

+1

爲什麼不在組件代碼中進行過濾* '* ngFor =「let model of filteredModels」'並且寫'get filteredModels(){...}'來提供它。你可以做同樣的事情來爲'select'元素提供一個唯一的條目數組。 – jonrsharpe

+0

*「我知道創建一個自定義管道將是正確的方式來做到這一點」 - 是什麼讓你得出這個結論? *「但我不知道如何寫一個」* - 那麼你有沒有考慮*學習?* – jonrsharpe

+2

當然jonrsharpe :)。我是新手,希望我能找到正確的方法。我讀了很多關於過濾角2的帖子,自定義管道主要被稱爲正確的選擇。 – gundra

回答

12

下面是一個示例管:

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

@Pipe({ 
    name: 'matchesCategory' 
}) 
export class MathcesCategoryPipe implements PipeTransform { 
    transform(items: Array<any>, category: string): Array<any> { 
     return items.filter(item => item.category === category); 
    } 
} 

要使用它:

<li *ngFor="let model; of models | matchesCategory:model.category" (click)="gotoDetail(model)"> 

=====爲plunkr例如====

您需要將您的選擇更改反映到某些變量中

首先在類中定義的成員:

selectedCategory: string; 

然後更新您的模板:

<select (change)="selectedCategory = $event.target.value"> 
    <option *ngFor="let model of models ">{{model.category}}</option> 
</select> 

最後,使用管道:看了之後

<li *ngFor="let model; of models | matchesCategory:selectedCategory" (click)="gotoDetail(model)"> 

====評論猛擊====

我注意到你用過諾言。 Angular2更加面向rxjs。所以,我會改變的第一件事是在你的服務,替換:

getModels(): Promise<Model[]> { 
    return Promise.resolve(MODELS); 
} 

到:

getModels(): Observable<Array<Model>> { 
    return Promise.resolve(MODELS); 
} 

getModels(id: number): Observable<Model> { 
    return getModels().map(models => models.find(model.id === id); 
} 

然後在ModelsComponent

models$: Observable<Array<Model>> = svc.getModels(); 
uniqueCategories$: Observable<Array<Model>> = this.models$ 
    .map(models => models.map(model => model.category) 
    .map(categories => Array.from(new Set(categories))); 

你的選擇將變成:

 <option *ngFor="let category; of uniqueCategories$ | async">{{model.category}}</option> 

和您的列表:

 <li *ngFor="let model; of models$ | async | matchesCategory:selectedCategory" (click)="gotoDetail(model)"> 

這是一個非常通風良好的解決方案,因爲你有很多重複和你保持查詢服務。以此爲出發點並僅查詢一次服務,然後從得到的結果中獲取特定值。

如果您想保留代碼,只需實現UniqueValuesPipe,則其轉換將獲得一個參數,並使用Array.from(new Set(...))過濾它以返回唯一類別。您需要先將其映射到字符串(類別)。

+0

謝謝梅爾,我會嘗試在我的項目中實現此代碼,以查看它是否給出結果。我會回到你的... thx – gundra

+0

梅爾,當我試圖通過使用此代碼篩選項目時,控制檯拋出錯誤「無法讀取屬性'類別的未定義」 – gundra

+0

添加一個斷點(或console.log(項目,類別)在功能的頂部,看到它得到的值正確 – Meir

相關問題