如何将filter应用于* ngFor

显然Angular2将使用pipe道而不是Angular1中的filter来结合ng-for来过滤结果,实现仍然看起来很模糊,没有明确的文档。

也就是说,我试图达到的目标可以从以下的观点来看

<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div> 

如何使用pipe道来实现?

基本上,你写一个pipe道,然后你可以在*ngFor指令中使用。

在你的组件中:

 filterargs = {title: 'hello'}; items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}]; 

在您的模板中,您可以将string,数字或对象传递到您的pipe道以用于过滤:

 <li *ngFor="let item of items | myfilter:filterargs"> 

在你的pipe道中:

 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中注册你的pipe道,你不再需要在你的@Component中注册pipe道

 import { MyFilterPipe } from './shared/pipes/my-filter.pipe'; @NgModule({ imports: [ .. ], declarations: [ MyFilterPipe, ], providers: [ .. ], bootstrap: [AppComponent] }) export class AppModule { } 

添加了一个Plunker,它演示了如何使用自定义滤镜pipe道和内置切片pipe道来限制结果。 您可以在这里查看和testing代码: https : //embed.plnkr.co/l1oTNT/

请注意(正如几位评论员指出的那样)Angular中没有内置filterpipe道是有原因的。 通过https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe了解更多信息;

简化的方法(由于性能问题,只能在小数组上使用)在大数组中,您必须通过代码手动进行过滤:

请参阅: https : //angular.io/docs/ts/latest/guide/pipes.html#!#no-filter-pipe

 @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> 

如果使用variables作为第二个参数,请不要使用引号。

很多你有很好的方法,但是这里的目标是通用的,并定义了一个数组pipe道,这个数组pipe道在所有与* 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)); } } 

然后在你的组件中,你需要实现一个具有以下标志(item:any)=> boolean的方法 ,例如,我把它称为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对于需要通过callback进行过滤的所有数组类都是非常通用的。 在mycase中,我发现它对于* ngFor类似的场景非常有用。

希望这可以帮助!!!

codematrix

您也可以使用以下内容:

 <template ngFor let-item [ngForOf]="itemsList"> <div *ng-if="conditon(item)"></div> </template> 

这只会显示div如果您的项目符合条件

有关更多信息,请参阅angular度文档如果还需要索引,请使用以下命令:

 <template ngFor let-item [ngForOf]="itemsList" let-i="index"> <div *ng-if="conditon(item, i)"></div> </template> 

我不确定什么时候进来,但他们已经做了切片pipe道,将做到这一点。 这也是有据可查的。

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> 

这是我没有使用pipe道实现的。

component.html

 <div *ngFor="let item of filter(itemsList)"> 

component.ts

 @Component({ .... }) export class YourComponent { filter(itemList: yourItemType[]): yourItemType[] { let result: yourItemType[] = []; //your filter logic here ... ... return result; } } 

根据这里和其他地方的答案,我创造了一个重​​拳。

此外,我必须添加一个@Input@ViewChildElementRef<input>并创build和subscribe()到它的observable。

Angular2searchfilter: PLUNKR

Angular2中的pipe道与命令行中的pipe道相似。 每一个前面的值的输出被input到filter之后,这样就很容易链接filter,就像这样:

 <template *ngFor="#item of itemsList"> <div *ngIf="conditon(item)">{item | filter1 | filter2}</div> </template> 

我创build了以下pipe道从列表中获取所需的项目。

 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); } } 

小写转换只是为了匹配不区分大小写的方式。 你可以像这样在你的视图中使用它:

 <div> <input type="text" placeholder="Search reward" [(ngModel)]="searchTerm"> </div> <div> <ul> <li *ngFor="let reward of rewardList | filter:searchTerm"> <div> <img [src]="reward.imageUrl"/> <p>{{reward.name}}</p> </div> </li> </ul> </div> 

理想情况下,你应该为此创buildangualr 2pipe道。 但是你可以做到这一点。

 <ng-container *ngFor="item in itemsList"> <div*ngIf="conditon(item)">{{item}}</div> </ng-container> 

我喜欢用于应用程序特定filter的另一种方法是在组件上使用自定义的只读属性,允许您比使用自定义pipe道(IMHO)更加干净地封装过滤逻辑。

例如,如果我想绑定到albumList并筛选albumList

 searchText: ""; albumList: Album[] = []; get filteredAlbumList() { if (this.config.searchText && this.config.searchText.length > 1) { var lsearchText = this.config.searchText.toLowerCase(); return this.albumList.filter((a) => a.Title.toLowerCase().includes(lsearchText) || a.Artist.ArtistName.toLowerCase().includes(lsearchText) ); } return this.albumList; } 

要在HTML中绑定,您可以绑定到只读属性:

 <a class="list-group-item" *ngFor="let album of filteredAlbumList"> </a> 

我发现特定于应用程序的filter比pipe道更好,因为它保持与组件相关的filter的逻辑。

pipe道可以更好地用于全球可重复使用的filter。

这是我之前创build的一个例子,并且包括一个正在工作的plunk。 它提供了一个可以过滤任何对象列表的filterpipe道。 你基本上只是在你的ngFor规范中指定属性和值{key:value}。

与@NateMay的回应没有什么不同,除了我详细解释它之外。

在我的情况下,我过滤了一些文本(filterText)上的无序列表,用户使用这种标记对数组中对象的“label”属性input:

 <ul> <li *ngFor="let item of _items | filter:{label: filterText}">{{ item.label }}</li> </ul> 

https://long2know.com/2016/11/angular2-filter-pipes/

基于上面提出的非常优雅的callbackpipe道解决scheme,通过允许传递附加的filter参数,可以进一步概括它。 然后我们有:

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>