如何根据对象属性字符串过滤“ngFor”循环内的项目

Posted

技术标签:

【中文标题】如何根据对象属性字符串过滤“ngFor”循环内的项目【英文标题】:How to filter items inside “ngFor” loop, based on object property string 【发布时间】:2017-04-03 10:22:42 【问题描述】:

我需要通过更改下拉列表中的类别来过滤 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

【问题讨论】:

为什么不在组件代码中做这个过滤?你可以做例如*ngFor="let model of filteredModels" 并写信 get filteredModels() ... 提供。您可以执行相同的操作来为 select 元素提供一组唯一条目。 “我知道创建自定义管道是正确的做法” - 是什么让您得出这个结论? “但我不知道怎么写”——那你有考虑过学习吗? 当然 jonrsharpe :)。我是这方面的新手,我希望我能找到正确的方法。我读了很多关于过滤角2的帖子,自定义管道主要被称为正确的选择.. 【参考方案1】:

这是一个示例管道:

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

==== 看到笨蛋后的cmets ====

我注意到你使用了 promise。 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(...)) 对其进行过滤以返回唯一类别。您需要先将其映射到字符串(类别)。

【讨论】:

感谢 Meir,我会尝试将此代码实现到我的项目中,看看它是否给出了结果。我会回复你...谢谢 Meir,当我尝试使用此代码过滤项目时,控制台向我抛出错误“无法读取未定义的属性‘类别’” 在函数顶部添加一个断点(或 console.log(items, category) 并查看它是否正确获取值 如果这不起作用,请将您的完整实现放在 plnkr 上,以便我看看 你在MathcesCategoryPipe 中有错字(Mathces)

以上是关于如何根据对象属性字符串过滤“ngFor”循环内的项目的主要内容,如果未能解决你的问题,请参考以下文章

Angular - 如何将 ngFor 过滤到特定的对象属性数据

如何在Angular中使用ngFor循环对象属性

如何将 ngFor 的动态索引添加到 html 属性值

更改ngFor循环中调用的组件内的父值

如何在视图中仅循环一次对象(单个 *ngFor)?

角度 6:在选择“选择”的值后尝试循环抛出一个对象(通过 *ngFor)