<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>
如何使用管道来实现?
#1 楼
基本上,您编写了一个管道,然后可以在*ngFor
指令中使用它。在组件中:
filterargs = {title: 'hello'};
items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
在模板中,您可以将字符串,数字或对象传递给管道以用于过滤:
< pre class =“ lang-none prettyprint-override”>
<li *ngFor="let item of items | myfilter:filterargs">
在您的管道中:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'myfilter',
pure: false
})
export class MyFilterPipe implements PipeTransform {
transform(items: any[], filter: Object): any {
if (!items || !filter) {
return items;
}
// filter items array, items which match and return true will be
// kept, false will be filtered out
return items.filter(item => item.title.indexOf(filter.title) !== -1);
}
}
请记住在
app.module.ts
中注册管道;您不再需要在您的@Component
中注册管道了 import { MyFilterPipe } from './shared/pipes/my-filter.pipe';
@NgModule({
imports: [
..
],
declarations: [
MyFilterPipe,
],
providers: [
..
],
bootstrap: [AppComponent]
})
export class AppModule { }
这里有一个演示的柱塞使用自定义过滤器管道和内置切片管道限制结果。在Angular中。
评论
谢谢,这是按预期工作的,但是有时最好检查是否定义了items数组而不是null,因为Ng2可能会尝试在“ items”仍未定义的情况下应用过滤器。
–timmz
16 Mar 17 '16 at 16:50
另外,我需要将过滤器类添加到@Component声明中。像这样:@Component({...管道:[MyFilterPipe]
–斯蒂芬
16年7月11日在18:01
我认为在数组为空的情况下,它也需要此行“ f(!items)返回项目”。
–BoštjanPišler
16年12月21日在16:02
Angular表示使用Pipe存在性能问题,因此建议对组件进行过滤
–塞巴斯蒂安·罗哈斯(SebastiánRojas)
17年7月17日在19:31
我想建议将* ngFor参数包装在括号中,以避免任何混淆并使它“防更改”:
– Tomas
18年5月25日在10:36
#2 楼
你们中的许多人都有很好的方法,但是这里的目标是通用并定义一个数组管道,该数组管道与* ngFor。callback.pipe.ts有关(在别忘了将其添加到模块的声明数组中)
import { PipeTransform, Pipe } from '@angular/core';
@Pipe({
name: 'callback',
pure: false
})
export class CallbackPipe implements PipeTransform {
transform(items: any[], callback: (item: any) => boolean): any {
if (!items || !callback) {
return items;
}
return items.filter(item => callback(item));
}
}
然后在您的组件中,您需要实现一个具有以下签名的方法(项目:any)=>布尔值(以我为例),我将其称为filterUser,用于过滤大于18岁的用户年龄。
您的组件
@Component({
....
})
export class UsersComponent {
filterUser(user: IUser) {
return !user.age >= 18
}
}
最后但同样重要的是,您的html代码将如下所示:
您的HTML
<li *ngFor="let user of users | callback: filterUser">{{user.name}}</li>
如您所见,此Pipe在所有数组(如需要通过回调过滤的项)中都是通用的。就我而言,我发现它对于* ngFor类似场景非常有用。
希望对您有所帮助!
codematrix
评论
我注意到在函数filterUser()或与之等效的函数中,您无法像使用组件类中的所有其他函数一样使用“ this”来访问当前组件实例。我需要访问组件对象以检查过滤后的项在集合中。
– Paul
17年11月16日在15:56
@Paul,嗯...那是不可能的。您的方法私密吗?没关系,因为private只是编译结构,不会在运行时强制执行。在我的示例中,我使用了IUser。这假定要迭代的集合中的项目映射到它。您可以尝试任何一种,看看是否可行。另外,请确保输入正确的名称,大小写和全部。
–code5
17年11月18日在3:54
我无法使用此方法访问组件变量
– suulisin
18年1月15日在16:52
为避免此问题未定义,您可以在您的组件上编写方法,例如filterUser =(user:IUser)=>而不是filteruser(user:IUser)
–汤姆
19年1月18日在16:41
@Paul我知道这对您有所帮助为时已晚,但它可能会对其他人有所帮助。之所以在组件方法上丢失它,是因为该方法被用作回调并应用了新的this上下文。您在面向对象的javascript中遇到了一个常见问题,但是有一个古老而又简单的解决方案:将要用作回调的方法绑定到原始类。在构造函数中,添加以下代码:this.myCallbackFunc = this.myCallbackFunc.bind(this);而已。您将再也不会失去它。
–兰多福
19年12月16日在16:32
#3 楼
简化的方法(由于性能问题,仅在小型阵列上使用。在大型阵列中,您必须通过代码手动制作过滤器):请参阅:https://angular.io/guide/pipes#appendix -no-filterpipe-or-orderbypipe
@Pipe({
name: 'filter'
})
@Injectable()
export class FilterPipe implements PipeTransform {
transform(items: any[], field : string, value : string): any[] {
if (!items) return [];
if (!value || value.length == 0) return items;
return items.filter(it =>
it[field].toLowerCase().indexOf(value.toLowerCase()) !=-1);
}
}
<li *ngFor="let it of its | filter : 'name' : 'value or variable'">{{it}}</li>
如果使用变量作为第二个参数,不要使用引号。
评论
也许添加以下内容以显示如何将其与ReqExp组合:return items.filter(item => {return new RegExp(value,“ i”)。test(item [field])});
–约翰内斯
16 Jun 30'15:25
根据Angular团队的说法,这被认为是不好的做法。
–user663031
17 Mar 15 '17 2:33
@torazaburo您可以参考他们的意见或解释原因吗?谢谢
–Zymotik
17年5月15日在22:32
@Zymotik参见angular.io/docs/ts/latest/guide/…。
–user663031
17年5月16日在3:27
根据Angular团队的说法,这是糟糕的代码,因为它运行缓慢且无法很好地缩小。该团队不希望由于其代码而看到缓慢的网站,因此这次他们没有将其构建到Angular中。 angular.io/docs/ts/latest/guide / ...
–Zymotik
17年5月23日在8:44
#4 楼
这是我在不使用管道的情况下实现的。component.html
br />
评论
我认为这会占用大量计算资源,因为Angular每次运行更改检测都会执行过滤器。它不能很好地扩展到大型阵列。较干净的代码(尽管对代码更复杂)解决方案是使itemList成为Observable并使用异步过滤器:异步。发生更改时,使可观察对象发出新列表。这样,过滤代码仅在需要时运行。
– BeetleJuice
17-09-25在11:06
该答案应为负分。不好,用管子。
–Cétia
2月14日15:54
我不确定我是否理解这很糟糕的原因,无论您使用什么,在更改检测期间管道或其他任何东西都不一定会被过滤掉吗?如果在管道中放置一个断点,您将看到它在每次更改检测时仍在运行。可观察的方法比trackBy有什么更好的方法,因为到最后还是需要根据值进行过滤可能会改变的变量的..?您可以使用单独的列表进行更新,然后再推送更改。
–丹·蔡斯(Dan Chase)
8月17日在16:05
#5 楼
我不确定它什么时候进来的,但是他们已经制作了可以做到这一点的切片管。https://angular.io/docs/ts/latest/api/common/index/SlicePipe-pipe.html
<p *ngFor="let feature of content?.keyFeatures | slice:1:5">
{{ feature.description }}
</p>
评论
如果使用trackBy接口,则必须在;之前应用切片管道。例如:* ngFor =“让内容具有功能吗?.keyFeatures | slice:1:5; trackBy功能?.id”
–菲利普
16年11月28日在12:50
#6 楼
您还可以使用以下命令:<template ngFor let-item [ngForOf]="itemsList">
<div *ng-if="conditon(item)"></div>
</template>
仅当您的商品符合条件时,才会显示div
有关更多信息,请参见角度文档。信息
如果还需要索引,请使用以下内容:
<template ngFor let-item [ngForOf]="itemsList" let-i="index">
<div *ng-if="conditon(item, i)"></div>
</template>
评论
这不是输入列表中每个项目的模板,而不是输入过滤后的列表吗?这可能会影响性能。
– Azeroth2b
18年7月6日在14:38
#7 楼
Angular2中的管道类似于命令行中的管道。每个先前值的输出都在管道之后输入到过滤器中,这使得过滤器的链接也很容易,如下所示:评论
抱歉,如果这令人误解,我的意思是* ng-for =“ itemsList的#item”中的变量item应该用于过滤结果,例如* ng-if =“ conditon(item)”。在此示例中不起作用。
–卡乐德
2015年12月8日在19:40
您可以将条件设为过滤器,并使用{{item | condition}}条件将仅返回满足条件的项目,否则将不返回任何值。
–本·格拉瑟(Ben Glasser)
15年12月8日在19:43
@BenGlasser我认为管道是从右到左应用的。因此,这将首先应用filter2,然后再应用filter1。
–伊文·普莱斯
16年1月25日在18:58
不支持同一元素上的* ngFor和* ngIf。您需要更改其中之一的显式形式
–GünterZöchbauer
16-4-6的3:58
@GünterZöchbauer我花了一年时间,但我更新了语法以反映您建议的更改
–本·格拉瑟(Ben Glasser)
17年5月12日19:00
#8 楼
我知道这是一个老问题,但是,我认为提供其他解决方案可能会有所帮助。等效于此AngularJS在Angular 2+中,您不能在同一元素上使用* ngFor和* ngIf,因此它将是:
<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>
,并且如果不能用作内部容器ng-container代替。
当您想在应用程序中有条件地追加一组元素(即使用* ngIf =“ foo”)但又不想用其他元素包装它们时,ng-container很有用。 br />
#9 楼
为此,我实现并发布了通用组件。请参阅https://www.npmjs.com/package/w-ng5
要使用此组件,请在使用npm安装此软件包之前:
npm install w-ng5 --save
之后,在app.module中导入模块
...
import { PipesModule } from 'w-ng5';
下一步,在app.module的声明部分添加:
imports: [
PipesModule,
...
]
示例使用
过滤简单字符串
<input type="text" [(ngModel)]="filtroString">
<ul>
<li *ngFor="let s of getStrings() | filter:filtroString">
{{s}}
</li>
</ul>
过滤复杂字符串-级别2中的字段'值'
<input type="text" [(ngModel)]="search">
<ul>
<li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.valor2', value: search}]">
{{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
</li>
</ul>
过滤复杂字符串-中间字段-级别1中的'值'
<input type="text" [(ngModel)]="search3">
<ul>
<li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.valor1', value: search3}]">
{{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
</li>
</ul>
过滤简单数组-字段'Nome'级别0
<input type="text" [(ngModel)]="search2">
<ul>
<li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'nome', value: search2}]">
{{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
</li>
</ul>
在树字段中过滤-级别2或'Valor'的字段'Valor' 1级或0级的'Nome'
<input type="text" [(ngModel)]="search5">
<ul>
<li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.valor2', value: search5}, {field:'n1.valor1', value: search5}, {field:'nome', value: search5}]">
{{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
</li>
</ul>
过滤不存在的字段-3级不存在的'Valor'
<input type="text" [(ngModel)]="search4">
<ul>
<li *ngFor="let s of getComplexTypesExtends() | filter:[{field:'n1.n2.n3.valor3', value: search4}]">
{{s.nome}} - {{s.idade}} - {{s.n1.valor1}} - {{s.n1.n2.valor2}}
</li>
</ul>
此组件可用于无限属性级别...
评论
嗨,我在这里,我已经完成了所有步骤,在这种情况下,我使用的是* ngFor =“ let inovice of invoices | filter:searchInvoice”,它会在我的列表中进行搜索,但显示空白列表,你知道为什么?
– jecorrales
18年2月2日在19:30
您好,请告诉我您的发票清单包含的对象的结构和类型是什么。仅当发票清单的类型为字符串时,才应使用它的使用方式。如果要按发票编号(invoice.number)进行搜索,请使用:* ngFor =“让发票发票|过滤器:{字段:编号,值:searchInvoice}”。如果要按两列进行过滤,例如invoice.customer.name,请使用:* ngFor =“ let inovice of invoices | filter:[field:number,value:searchInvoice},{field:customer.name,value: searchInvoice}]。
–温德森·金塔尼尔·达席尔瓦(Wedson Quintanilha da Silva)
18-11-3在22:04
#10 楼
管道将是最好的方法。但下面的一个也可以。<div *ng-for="#item of itemsList">
<ng-container *ng-if="conditon(item)">
// my code
</ng-container>
</div>
评论
这可能会破坏某些东西。例如在垫子形式的领域内
–pcnate
18年8月21日在21:54
#11 楼
与Angular 6一起使用的用于过滤ngFor的简单解决方案如下: <span *ngFor="item of itemsList" >
<div *ngIf="yourCondition(item)">
your code
</div>
</span
跨度很有用,因为它并不固有地表示任何东西。
评论
比更好的方法是使用
– Trevor de Koekkoek
19/12/30在14:50
我真是个书呆子,这真使我大笑,我认为是由于从通常建议的过滤ngFor逻辑中意外转移了代码。由内而外的俄罗斯娃娃,但看起来仍然和以前一样吗?有谁知道这比对ngFor进行过滤的结果相同,更好还是更坏?真的很好奇!
–丹·蔡斯(Dan Chase)
8月17日15:48
#12 楼
我根据这里和其他地方的答案创建了一个小矮人。另外,我还必须添加
@Input
的@ViewChild
,ElementRef
和<input>
,并在其可观察到的位置创建subscribe()
。不再有效)#13 楼
基于上面提出的非常优雅的回调管道解决方案,可以通过允许传递其他过滤器参数来进一步概括它。然后我们有:callback.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'callback',
pure: false
})
export class CallbackPipe implements PipeTransform {
transform(items: any[], callback: (item: any, callbackArgs?: any[]) => boolean, callbackArgs?: any[]): any {
if (!items || !callback) {
return items;
}
return items.filter(item => callback(item, callbackArgs));
}
}
组件
filterSomething(something: Something, filterArgs: any[]) {
const firstArg = filterArgs[0];
const secondArg = filterArgs[1];
...
return <some condition based on something, firstArg, secondArg, etc.>;
}
html
<li *ngFor="let s of somethings | callback : filterSomething : [<whatWillBecomeFirstArg>, <whatWillBecomeSecondArg>, ...]">
{{s.aProperty}}
</li>
评论
好主意,鼓掌👏
–visar_uruqi
10月3日,22:40
#14 楼
这是我的代码:import {Pipe, PipeTransform, Injectable} from '@angular/core';
@Pipe({
name: 'filter'
})
@Injectable()
export class FilterPipe implements PipeTransform {
transform(items: any[], field : string, value): any[] {
if (!items) return [];
if (!value || value.length === 0) return items;
return items.filter(it =>
it[field] === value);
}
}
示例:
LIST = [{id:1,name:'abc'},{id:2,name:'cba'}];
FilterValue = 1;
<span *ngFor="let listItem of LIST | filter : 'id' : FilterValue">
{{listItem .name}}
</span>
#15 楼
我喜欢用于特定于应用程序的筛选器的另一种方法是在组件上使用自定义只读属性,该属性使您可以比使用自定义管道(IMHO)更加简洁地封装筛选逻辑。例如,如果我想绑定到
albumList
并在searchText
上进行过滤:我发现对于特定于应用程序的专用过滤器,它比管道更有效,因为它与组件保持了与过滤器有关的逻辑。 管道对于全局可重用的过滤器效果更好。
评论
此方法不会触发连续的脏检查,而不是使用valueChanged方法吗?
–LéonPelletier
16 Dec 1'在19:22
#16 楼
我创建了以下管道,以从列表中获取所需的项目。您的看法是这样的:-import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any[], filter: string): any {
if(!items || !filter) {
return items;
}
// To search values only of "name" variable of your object(item)
//return items.filter(item => item.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1);
// To search in values of every variable of your object(item)
return items.filter(item => JSON.stringify(item).toLowerCase().indexOf(filter.toLowerCase()) !== -1);
}
}
#17 楼
理想情况下,您应该为此创建角度2管道。但是您可以做到这一点。<ng-container *ngFor="item in itemsList">
<div*ngIf="conditon(item)">{{item}}</div>
</ng-container>
#18 楼
这是我创建了一段时间并在博客上发布的示例,其中包含一个正在工作的插件。它提供了一个过滤器管道,可以过滤任何对象列表。基本上,您只需要在ngFor规范中指定属性和值{key:value}。以我为例,我使用这种标记对用户输入的某些文本(filterText)进行了过滤,以针对我数组中对象的“ label”属性:
<ul>
<li *ngFor="let item of _items | filter:{label: filterText}">{{ item.label }}</li>
</ul>
https://long2know.com/2016/11/angular2-filter-pipes/
#19 楼
使用component.ts文件中的@Pipe
创建过滤器的第一步:your.component.ts
import { Component, Pipe, PipeTransform, Injectable } from '@angular/core';
import { Person} from "yourPath";
@Pipe({
name: 'searchfilter'
})
@Injectable()
export class SearchFilterPipe implements PipeTransform {
transform(items: Person[], value: string): any[] {
if (!items || !value) {
return items;
}
console.log("your search token = "+value);
return items.filter(e => e.firstName.toLowerCase().includes(value.toLocaleLowerCase()));
}
}
@Component({
....
persons;
ngOnInit() {
//inicial persons arrays
}
})
以及Person的数据结构对象:
person.ts
export class Person{
constructor(
public firstName: string,
public lastName: string
) { }
}
html文件中的视图:
your.component.html
<input class="form-control" placeholder="Search" id="search" type="text" [(ngModel)]="searchText"/>
<table class="table table-striped table-hover">
<colgroup>
<col span="1" style="width: 50%;">
<col span="1" style="width: 50%;">
</colgroup>
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let person of persons | searchfilter:searchText">
<td>{{person.firstName}}</td>
<td>{{person.lastName}}</td>
</tr>
</tbody>
</table>
#20 楼
这是您的数组products: any = [
{
"name": "John-Cena",
},
{
"name": "Brock-Lensar",
}
];
这是您的ngFor循环
筛选器:
<input type="text" [(ngModel)]='filterText' />
<ul *ngFor='let product of filterProduct'>
<li>{{product.name }}</li>
</ul>
在那里,我正在使用产品的filterProduct即时产品,因为我想保留我的原始数据。
这里_filterText模型用作输入框。每当有任何更改时,setter函数都会调用。
在setFilterText中调用performProduct时,它将仅返回与输入匹配的结果。我使用小写字母,不区分大小写。
filterProduct = this.products;
_filterText : string;
get filterText() : string {
return this._filterText;
}
set filterText(value : string) {
this._filterText = value;
this.filterProduct = this._filterText ? this.performProduct(this._filterText) : this.products;
}
performProduct(value : string ) : any {
value = value.toLocaleLowerCase();
return this.products.filter(( products : any ) =>
products.name.toLocaleLowerCase().indexOf(value) !== -1);
}
#21 楼
经过一番谷歌搜索后,我遇到了ng2-search-filter
。 In将获取您的对象并将搜索词应用于所有对象属性以寻找匹配项。#22 楼
我正在寻找使通过对象的过滤器的方法,然后可以像多重过滤器一样使用它:import { PipeTransform, Pipe } from '@angular/core';
@Pipe({
name: 'filterx',
pure: false
})
export class FilterPipe implements PipeTransform {
transform(items: any, filter: any, isAnd: boolean): any {
let filterx=JSON.parse(JSON.stringify(filter));
for (var prop in filterx) {
if (Object.prototype.hasOwnProperty.call(filterx, prop)) {
if(filterx[prop]=='')
{
delete filterx[prop];
}
}
}
if (!items || !filterx) {
return items;
}
return items.filter(function(obj) {
return Object.keys(filterx).every(function(c) {
return obj[c].toLowerCase().indexOf(filterx[c].toLowerCase()) !== -1
});
});
}
}
slotFilter:any={start:'',practitionerCodeDisplay:'',practitionerName:''};
componet.html
<tr>
<th class="text-center"> <input type="text" [(ngModel)]="slotFilter.start"></th>
<th class="text-center"><input type="text" [(ngModel)]="slotFilter.practitionerCodeDisplay"></th>
<th class="text-left"><input type="text" [(ngModel)]="slotFilter.practitionerName"></th>
<th></th>
</tr>
<tbody *ngFor="let item of practionerRoleList | filterx: slotFilter">...
#23 楼
我使用了一个动态过滤器管道。源数据:
items = [{foo: 'hello world'}, {foo: 'lorem ipsum'}, {foo: 'foo bar'}];
在模板中,可以在任何对象属性中设置过滤器:
<li *ngFor="let item of items | filter:{foo:'bar'}">
管道:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter',
})
export class FilterPipe implements PipeTransform {
transform(items: any[], filter: Record<string, any>): any {
if (!items || !filter) {
return items;
}
const key = Object.keys(filter)[0];
const value = filter[key];
return items.filter((e) => e[key].indexOf(value) !== -1);
}
}
不要忘记在您的
app.module.ts
声明中注册管道
评论
请注意,针对哈希符号的ngFor在beta 17中引入了重大更改。正确的方法是:angulartutorial.net/2016/06/…
来自Gunter的@MemetOlsen评论如下:“不支持同一元素上的* ngFor和* ngIf。您需要更改其中一个的显式形式”
即使这是OP的要求,也建议不要在Angular2 +中使用PIPE进行过滤或排序。最好具有带有过滤值的class属性:angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe