显然,Angular 2将像在Angular1中一样使用管道而不是过滤器,并结合ng-for来过滤结果,尽管实现看起来仍然很模糊,没有明确的文档。
也就是说,我想要达到的目标可以从以下角度来看待
<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>
如何实现这样使用管道?
显然,Angular 2将像在Angular1中一样使用管道而不是过滤器,并结合ng-for来过滤结果,尽管实现看起来仍然很模糊,没有明确的文档。
也就是说,我想要达到的目标可以从以下角度来看待
<div *ng-for="#item of itemsList" *ng-if="conditon(item)"></div>
如何实现这样使用管道?
当前回答
这是我的代码:
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>
其他回答
我喜欢用于特定于应用程序的过滤器的另一种方法是在组件上使用自定义只读属性,这允许您比使用自定义管道(IMHO)更清晰地封装过滤逻辑。
例如,如果我想绑定到albumList并过滤searchText:
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>
我发现对于特定于应用程序的专用过滤器,这比管道工作得更好,因为它保持了与组件过滤器相关的逻辑。
管道对于全局可重用过滤器工作得更好。
基于上面提出的非常优雅的回调管道解决方案,可以通过允许传递额外的过滤器参数来进一步泛化它。然后我们有:
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>
下面给出了限制ngFor的最简单易行的方法
<li *ngFor="let item of list | slice:0:10;Let i=index" class="dropdown-item" >{{item.text}}</li> .text}
基本上,你写了一个管道,然后在*ngFor指令中使用。
在你的组件中:
filterargs = {title: 'hello'};
items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
在你的模板中,你可以将字符串,数字或对象传递给你的管道来过滤:
<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 { }
下面是一个Plunker,它演示了使用自定义过滤管道和内置切片管道来限制结果。
请注意(正如一些评论员指出的那样),Angular中没有内置过滤器管道是有原因的。
这是你的数组
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 instant,因为我想保留原始数据。 这里model _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);
}