【问题标题】:Angular 4 - Conditional *ngFor that displays every 3rd elementAngular 4 - 显示每个第三个元素的条件 *ngFor
【发布时间】:2018-02-14 07:14:36
【问题描述】:

我有一个 ngFor 循环,我希望它只遍历数组中的每个第三个元素,就像我希望下面的代码工作一样:

for(let i=0; i<array.length; i=i+3)...

我当前的 ngFor 代码如下:

<md-card class="cardContainer" *ngFor="let viz of visualisationList; let i = index">
    <md-card-header>
        <md-card-title>{{ viz['Title'] }}</md-card-title>
        <md-card-subtitle>Datasets: {{ viz['Datasets'] }}</md-card-subtitle>
    </md-card-header>
</md-card>

在 ngFor 循环中是否有一种简单的方法可以做到这一点?我可以在 ngInit() 中使用 typescript 预过滤成 3 个数组,或者我可以使用 ngIf 和模函数,但我希望我可以直接在 ngFor 循环中完成。

【问题讨论】:

    标签: angular loops ngfor


    【解决方案1】:

    在我看来,最简单且最简洁的方法是使用 Array.filter 和像这样的 getter 过滤组件逻辑中的数组:

    public get filteredArray() {
        return this.array.filter((value, index) => index % 3 === 0);
    }
    

    并为您的ngFor 使用过滤后的数组。

    注意:如果你的数组被装饰为输入,它可能是undefined,你应该用一个空数组初始化它,或者在使用filter之前检查getter内部是否未定义方法。

    【讨论】:

    • 我认为这种方式很简单,但我仍然希望在 HTML 中实现。即使我不走 HTML 路径,我仍然想知道它是否可能。
    • 可以使用ngFor、索引和ngIf 的组合,但您应该尽可能将“逻辑”排除在模板之外。
    【解决方案2】:

    您可能会为此使用Pipe 过滤器。但是,您仍然需要定义它以使其为组件所知。有一个内置的SlicePipe,这不是您想要的,但非常相似。基于此,我猜你可以使用:

    @Pipe({name: 'thirdelement', pure: false})
    export class ThirdElementPipe implements PipeTransform {
      transform(value: any): any {
        if (value == null) return value;
    
        if (!this.supports(value)) {
          throw invalidPipeArgumentError(ThirdElementPipe, value);
        }
    
        return value.filter((v, i) => (i % 3 == 0));
      }
    
      private supports(obj: any): boolean { return typeof obj === 'string' || Array.isArray(obj); }
    }
    

    并像使用它

    <md-card class="cardContainer" *ngFor="let viz of visualisationList | thirdelement; let i = index">
    

    或者更通用的SkipPipe

    @Pipe({name: 'skip', pure: false})
    export class SkipPipeimplements PipeTransform {
      transform(value: any, amount: number): any {
        if (value == null) return value;
    
        if (!this.supports(value)) {
          throw invalidPipeArgumentError(SkipPipe, value);
        }
    
        return value.filter((v, i) => (i % amount == 0));
      }
    
      private supports(obj: any): boolean { return typeof obj === 'string' || Array.isArray(obj); }
    }
    

    这应该可以像

    一样使用
    <md-card class="cardContainer" *ngFor="let viz of visualisationList | skip:3; let i = index">
    

    【讨论】:

    • 有趣的方法 - 我以前从未见过这样的事情。但我从您的回复中猜测,ngFor 中没有任何 Angular 本机可以让我做我想做的事情。我宁愿只编写一个返回具有正确元素的数组的函数,也不愿走这条路——但感谢您提供有趣的方法。我应该在问题中指定我正在寻找只需要在 HTML 中进行修改的内容。
    • 我不知道纯 HTML 方法,例如在 &lt;md-card-header&gt; 中使用 *ngIf="i%3==0" 进行过滤。然而,虽然管道方法需要一些 javascript,但您只需要在模块中定义该管道一次。之后,您可以在模块的所有模板中使用它。这取决于您的用例可能是否值得。
    • 喜欢这种新方法,并且仍然从中学到了一些新东西,但不幸的是,这不是我在问题中所要寻找的。不过感谢您提供新知识。
    • FilterPipe 是 Angular2 中的反模式之一,仅供参考。阅读此处了解更多信息:angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe
    【解决方案3】:

    您可以将 ngFor 上移一层到 ng-container 并在 md 卡上使用 ngIf/modulo,但我认为最好在数据到达视图之前准备好您的数据,个人。

    【讨论】:

    • 是的,我知道。想知道是否可以直接在 ngFor 循环中完成所有操作。我知道您可以将 if-then-else 条件添加到 ngFor 循环,但我还没有看到这样的情况。
    猜你喜欢
    • 2023-03-23
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2019-01-30
    • 2011-06-18
    • 1970-01-01
    • 2022-10-01
    相关资源
    最近更新 更多