ChatGPT解决这个技术问题 Extra ChatGPT

如何对 *ngFor 应用过滤器?

显然,Angular 2 将使用管道而不是 Angular1 中的过滤器,并结合 ng-for 来过滤结果,尽管实现似乎仍然模糊,没有明确的文档。

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

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

如何使用管道来实现?

请注意,在 beta 17 中为 ngFor 引入了关于哈希符号的重大更改。正确的方法是:<div *ngFor="let item of itemsList" *ngIf="conditon(item)" ...
下面来自 Gunter 的 @MemetOlsen 评论:“不支持同一元素上的 *ngFor*ngIf。您需要将其中一个更改为显式形式”
即使这是 OP 所要求的,也建议不要使用 PIPE 在 Angular2+ 中进行过滤或排序。更喜欢具有过滤值的类属性:angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe

M
Michael

基本上,您编写一个管道,然后您可以在 *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 { }

Here's a Plunker 演示了使用自定义过滤器管道和内置切片管道来限制结果。

请注意(正如几位评论员所指出的)there is a reason 为什么 Angular 中没有内置过滤器管道。


谢谢,这项工作按预期工作,但有时最好检查项目数组是否已定义且不为空,因为 Ng2 可能会在“项目”仍未定义时尝试应用过滤器。
此外,我需要将过滤器类添加到@Component 声明中。像这样:@Component({... 管道:[MyFilterPipe]
我认为它还需要这条线 ìf (!items) return items;` 以防数组为空。
Angular 说使用 Pipe 会出现性能问题,因此建议对组件进行过滤
我想建议将 *ngFor 参数括在括号中,以避免任何混淆并使其“防更改”:<li *ngFor="let item of (items | myfilter:filterargs)">
S
Slava Fomin II

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

然后在您的组件中,您需要实现一个具有以下签名(项目:任何)=> 布尔值的方法,例如,在我的例子中,我称之为 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>

如您所见,此管道在所有数组中都相当通用,例如需要通过回调过滤的项目。在我的情况下,我发现它对于 *ngFor 之类的场景非常有用。

希望这可以帮助!!!

代码矩阵


我注意到在函数 filterUser() 或我的等效函数中,您不能像使用组件类中的所有其他函数一样使用“this”来访问当前组件实例。我需要访问组件对象以检查过滤的项目是否在集合中。
@code5 昨天,当我尝试访问它时它没有工作。它说这是未定义的。
@Paul,嗯……那是不可能的。你的方法是私有的吗?这并不重要,因为私有只是编译构造并且在运行时不强制执行。在我的示例中,我使用了 IUser。这假设被迭代的集合中的项目映射到它。你可以尝试任何一个,看看它是否有效。另外,请确保名称输入正确,大小写和全部。
为避免 this 未定义的问题,您可以在组件上编写方法,例如 filterUser = (user: IUser) => 而不是 filteruser(user: IUser)
@Paul 我知道这对你来说太晚了,但它可能会帮助其他人。您在组件方法上丢失 this 的原因是该方法被用作回调并且应用了新的 this 上下文。您在面向对象的 javascript 中遇到了一个常见问题,但有一个古老而简单的解决方案:您绑定方法以用作原始类的回调。在您的构造函数中,添加以下代码: this.myCallbackFunc = this.myCallbackFunc.bind(this); 就是这样。您永远不会再失去 this
R
Rodolfo Jorge Nemer Nogueira

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

请参阅: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]) });
根据 Angular 团队的说法,这被认为是不好的做法。
@torazaburo 你能参考他们的意见或解释原因吗?谢谢
根据 Angular 团队的说法,这是一个糟糕的代码,因为它很慢而且没有很好地缩小。该团队不想因为他们的代码而看到缓慢的网站,所以这次他们没有将它构建到 Angular 中。 angular.io/docs/ts/latest/guide/…
S
Siegen

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

组件.html

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

组件.ts

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

我认为这将是计算密集型的,因为 Angular 每次运行更改检测时都会执行过滤器。它不能很好地扩展到大型阵列。一个更简洁但代码更复杂的解决方案是将 itemList 设为 Observable 并使用异步过滤器:let item of itemsList | async。当发生变化时,让 observable 发出新的列表。这样,过滤代码仅在需要时运行。
这个答案应该有一个负分。不好,用管子。
我不确定我是否理解为什么这太糟糕了,无论您使用什么,管道或其他任何东西都必须在更改检测期间潜在地过滤掉吗?如果您在管道中放置一个断点,您会看到它仍然在每次更改检测时运行。. 可观察方法比 trackBy 更好,因为仍然,在一天结束时,它需要根据值进行过滤可能已经改变的变量..?您可以使用单独的列表并更新,然后也可以推送更改。
M
Mark

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

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 Interface,则必须在 ; 之前应用切片管道。例如:*ngFor="let feature of content?.keyFeatures | slice:1:5; trackBy feature?.id"
M
Michael V

一个与 Angular 6 一起用于过滤 ngFor 的简单解决方案,如下所示:

你的代码

跨度很有用,因为它本身并不代表任何东西。


更好的是使用 因为它不会添加任何不必要的标记,除了 html 噪音可能会影响您的 CSS。
我是个书呆子,这让我真的笑出声来,我认为是由于通常推荐的逻辑过滤 ngFor 的意外转移。由内而外的俄罗斯娃娃,但看起来还是和以前一样?有谁知道这是否与在 ngFor 上过滤相同、更好或更差?真的很好奇!
不应在模板中使用函数
J
Jeroen

您还可以使用以下内容:

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

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

有关详细信息,请参阅 angular documentation 如果您还需要索引,请使用以下内容:

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

这不会为列表中的每个项目输入模板,而不仅仅是过滤列表吗?这可能会影响性能。
B
Ben Glasser

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

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

抱歉,如果这具有误导性,我的意思是 *ng-for="#item of itemsList" 中的变量 item 应该用于过滤结果,例如 *ng-if="conditon(item)"。这在这个例子中不起作用..
您可以将条件设为过滤器并使用 {{item |如果条件满足,条件}} 将只返回 item,否则不返回值。
@BenGlasser 我认为管道是从右到左应用的。所以这将首先应用 filter2,然后是 filter1。
不支持同一元素上的 *ngFor*ngIf。您需要更改其中之一的显式形式 <template ngFor ...>
@GünterZöchbauer 我花了一年时间,但我更新了语法以反映您建议的更改
t
tgralex

我知道这是一个老问题,但是,我认为提供另一种解决方案可能会有所帮助。

相当于这个的AngularJS

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

在 Angular 2+ 中,您不能在同一个元素上使用 *ngFor 和 *ngIf,因此它将如下所示:

<div *ngFor="let item of itemsList">
     <div *ngIf="conditon(item)">
     </div>
</div>

如果您不能用作内部容器,请改用 ng-container。 ng-container 在您想有条件地在应用程序中附加一组元素(即使用 *ngIf="foo")但又不想用另一个元素包装它们时很有用。


B
BlackSlash

我使用了一个动态过滤器管道

源数据:

items = [{foo: 'hello world'}, {foo: 'lorem ipsum'}, {foo: 'foo bar'}];

在模板中,您可以在任何对象 attr 中动态设置过滤器:

<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 声明中注册管道


W
Wedson Quintanilha da Silva

针对这个需求,我实现并发布了一个通用组件。看

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”或级别 1 中的“Valor”或级别 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",它正在我的列表中搜索,但显示一个空白列表,你知道为什么吗?
您好,请告诉我您的发票清单包含的对象的结构和类型是什么。只有当您的发票列表是字符串类型时,才应应用您使用它的方式。如果要按发票编号 (invoice.number) 搜索,请使用:*ngFor = "let inovice of invoices | filter: {field: number, value: searchInvoice}"。如果要按两列过滤,例如 invoice.customer.name,使用:*ngFor = "let inovice of invoices | filter: [field: number, value: searchInvoice}, {field: customer.name, value:搜索发票}]。
H
Hardik Patel

管道将是最好的方法。但低于一个也可以。

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

这可能会破坏某些事情。例如在 mat-form-field 内
N
Nate May

我根据这里和其他地方的答案创建了一个 plunker。

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

Angular2 搜索过滤器:PLUNKR(更新:plunker 不再工作)


B
Blablalux

基于上面提出的非常优雅的回调管道解决方案,可以通过允许传递额外的过滤器参数来进一步概括它。然后我们有:

回调.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>

好主意,鼓掌👏
P
Pàldi Gergő

这是我的代码:

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>

R
Rick Strahl

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

例如,如果我想绑定到 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>

我发现对于特定于应用程序的专用过滤器,这比管道更有效,因为它将与过滤器相关的逻辑与组件保持在一起。

管道更适合全局可重复使用的过滤器。


这种方法不会触发连续的脏检查而不是使用 valueChanged 方法吗?
S
Sanchit Tandon

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

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>

P
Peter Huang

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

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

l
long2know

这是我不久前创建的一个示例,并在博客中提到,其中包括一个有效的 plunk。它提供了一个过滤管道,可以过滤任何对象列表。您基本上只需在 ngFor 规范中指定属性和值 {key:value} 。

这与@NateMay 的回复并没有太大的不同,只是我用相对冗长的细节进行了解释。

在我的例子中,我使用这种标记过滤了用户针对我数组中对象的“标签”属性输入的一些文本(filterText)的无序列表:

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

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


P
Piotr Rogowski

在您的 component.ts 文件中使用 @Pipe 创建过滤器的第一步:

你的.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对象的数据结构:

个人.ts

export class Person{
    constructor(
        public firstName: string,
        public lastName: string
    ) { }
}

在您的 html 文件视图中:

你的.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>

G
Gajender Singh

这是你的数组

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 用作输入框。每当有任何更改设置器函数都会调用。在 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);
        }

a
alindber

经过一番谷歌搜索,我发现了 ng2-search-filter。 In 将获取您的对象并将搜索词应用于所有对象属性以寻找匹配项。


R
Richard Aguirre

https://i.stack.imgur.com/VnazQ.png

我做了这个美容解决方案:

过滤器.pipe.ts

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

组件.ts

slotFilter:any={start:'',practitionerCodeDisplay:'',practitionerName:''};

组件.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">...

Y
Yisal Khan

下面给出了限制您的 ngFor 的最简单易行的方法

<li *ngFor="let item of list | slice:0:10; let i=index" class="dropdown-item" >{{item.text}}</li>


H
Hoan Danh

你可以这样做:

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

或者

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

这种方法的主要问题是索引,并且可能 first 和 last 不再是可靠的值