web-dev-qa-db-ja.com

オブジェクトプロパティ文字列に基づいて、「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',
},

...
];

また、ドロップダウンリストには、繰り返されるカテゴリ名が含まれています。一意のカテゴリ(文字列)のみをリストする必要があります。

カスタムパイプを作成することがこれを行う正しい方法であることは知っていますが、どのように記述するかはわかりません。

プランカー: http://plnkr.co/edit/tpl:2GZg5pLaPWKrsD2JRted?p=preview

11
gundra

サンプルパイプを次に示します。

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

重複が多く、サービスのクエリを継続するため、これは非常にドラフトなソリューションです。これを出発点として、サービスを1回だけ照会し、得られた結果から特定の値を導き出します。

コードを保持したい場合は、UniqueValuesPipeを実装するだけで、そのトランスフォームは単一のパラメーターを取得し、Array.from(new Set(...))を使用して一意のカテゴリーを返すようにフィルターします。ただし、最初に文字列(カテゴリ)にマップする必要があります。

18
Meir