关于角度:如何将过滤器应用于* ngFor?

How to apply filters to *ngFor?

显然,Angular 2将使用管道代替Angular1中的ng-for过滤器来过滤结果,尽管实现起来似乎还很模糊,没有明确的文档。

即我可以从以下角度看待我要实现的目标

1
 

如何使用管道来实现?


基本上,您编写了一个管道,然后可以在*ngFor指令中使用它。

在您的组件中:

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

在模板中,您可以将字符串,数字或对象传递到管道以用于过滤:

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

在您的管道中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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中注册管道

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { MyFilterPipe } from './shared/pipes/my-filter.pipe';

@NgModule({
    imports: [
        ..
    ],
    declarations: [
        MyFilterPipe,
    ],
    providers: [
        ..
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

这是一个Plunker,它演示了如何使用自定义过滤器管道和内置切片管道来限制结果。

请注意(正如一些评论家所指出的那样),Angular中没有内置过滤器管道是有原因的。


你们中的许多人都有很好的方法,但是这里的目标是通用并定义一个数组管道,该数组管道在与* ngFor相关的所有情况下都可以重用。

callback.pipe.ts(不要忘记将其添加到模块的声明数组中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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岁的用户。

您的组件

1
2
3
4
5
6
7
8
@Component({
  ....
})
export class UsersComponent {
  filterUser(user: IUser) {
    return !user.age >= 18
  }
}

最后但并非最不重要的一点,您的html代码将如下所示:

您的HTML

1
2
<li *ngFor="let user of users | callback: filterUser">{{user.name}}
</li>

如您所见,此Pipe在需要通过回调过滤的所有数组(如项)中是相当通用的。在mycase中,我发现它对于* ngFor这样的场景非常有用。

希望这可以帮助!!!

码矩阵


简化方式(由于性能问题,仅在小型阵列上使用。在大型阵列中,您必须通过代码手动制作过滤器):

参见:https://angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

1
2
3
4
5
6
7
8
9
10
11
12
@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);
    }
}

用法:

1
2
<li *ngFor="let it of its | filter : 'name' : 'value or variable'">{{it}}
</li>

如果将变量用作第二个参数,请不要使用引号。


这是我在不使用管道的情况下实现的。

component.html

1
 

component.ts

1
2
3
4
5
6
7
8
9
10
11
12
@Component({
....
})
export class YourComponent {
  filter(itemList: yourItemType[]): yourItemType[] {
    let result: yourItemType[] = [];
    //your filter logic here
    ...
    ...
    return result;
  }
}


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

https://angular.io/docs/ts/latest/api/common/index/SlicePipe-pipe.html

1
2
3
4
<p *ngFor="let feature of content?.keyFeatures | slice:1:5">
   {{ feature.description }}

</p>


您还可以使用以下内容:

1
2
3
<template ngFor let-item [ngForOf]="itemsList">
   
</template>

仅当您的商品符合条件时才显示div

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

1
2
3
<template ngFor let-item [ngForOf]="itemsList" let-i="index">
   
</template>


Angular2中的管道类似于命令行中的管道。每个先前值的输出在管道之后被馈送到过滤器中,这使得链接过滤器变得容易,如下所示:

1
2
3
<template *ngFor="#item of itemsList">
    {item | filter1 | filter2}
</template>