【问题标题】:how to count *ngif inside *ngfor如何在 *ngfor 中计算 *ngif
【发布时间】:2021-09-08 04:36:56
【问题描述】:

我想知道下面这段代码显示了多少项。

component.html:

<p *ngIf="counter">{{counter}} items displayed!</p>
<p *ngIf="!counter">Nothing to display!</p>

<ng-container *ngFor="let item of items">
  <li *ngIf="item.count < 100">{{counter}}. {{item.title}}</li>
</ng-container>

component.ts:

export class ListComponent {
  @Input('items') items: any[];

  constructor() { }

  protected counter: number = 0;
}

项目(json 演示):

[
    {id: 1, count: 100, title: "title #1"},
    {id: 2, count: 20, title: "title #2"},
    {id: 3, count: 0, title: "title #3"},
    {id: 4, count: 200, title: "title #4"},
    {id: 5, count: 100, title: "title #5"},
]

注意 1:在上面的示例数据中,只有数组中对象的 count 属性可以在任何时候被应用程序的任何其他组件更改。

注意 2:实际上,items 是一个数组数组,但为了更好地表示和更好地理解,我在这里将其更改为对象数组。


我试图计算 HTML 节点,但发生了这个错误:

NG0100: ExpressionChangedAfterItHasBeenCheckedError

我也尝试过 *ngIf="addCounter(item.count

我也无法过滤ts文件中的items(有很多ngfors并且items不断更新,所以ts文件因为一个简单的计数器而变得过于复杂)。

有没有更好的方法?

【问题讨论】:

    标签: angular


    【解决方案1】:

    您应该在组件类中完成所有数据过滤、处理和准备工作。该模板应仅用于显示数据。这是根据问题中提到的条件显示项目的一些方法:

    组件.ts

    filteredItems = items.filter(item => item.count < 100);
    counter = filteredItems.length;
    

    模板.html

    <p *ngIf="counter">{{counter}} items displayed!</p>
    <p *ngIf="!counter">Nothing to display!</p>
    
    <ng-container *ngFor="let item of filteredItems; let i = index">
      <li>{{i}}. {{item.title}}</li>
    </ng-container>
    

    【讨论】:

    • 谢谢,但是items 是通过@Input() 发送到组件的。我应该把过滤线放在哪里?还有当items 更改时如何更新它?
    • 完全没有问题,您可以使用ngOnChanges检测@Input 更改
    • 似乎 ngOnChanges() 没有检测到内部项目的变化,例如items[index].count。可能只检测到items 本身的更改?! (在我的应用程序中,items 数组中对象的count 属性已更新,但items 数组中的对象总数根本没有改变)。
    • 您可以在输入上使用 set 属性,通过创建过滤器来进行更改。
    【解决方案2】:

    根据cmets,可以在TS文件中添加一个计数器,添加一个每次递增的方法item.counter &lt; 100

    已根据问题中提供的评论和额外信息更新答案

    您可以在input 上使用set 属性。在 ts 文件中创建两个变量:counter(已经存在)和itemList

    export class ListComponent {
      protected counter: number = 0;
      public itemList: Array<any>= [];
      @Input('items') set item (value) {
          console.log(value) // now you get items here
          this.itemList = value;
          this.filterBasedOnCount(value);
      }
    
      constructor() { }
      
      filterBasedOnCount(items) {
         this.counter =  items.filter(item => item.count < 100).length;
      }
      
    }
    

    注 2:实际上,items 是一个数组数组,但为了更好 表示和更好的理解我把它改成了数组 对象在这里。

    您可以在过滤器中使用 flatMap 来获取仅用于计数目的的对象列表。

    【讨论】:

    • 我想显示 items.count )。谢谢,但我要的不是一个简单的 *ngfor 索引。
    • 更新答案,如果有帮助请检查一下。
    • 我已经尝试过了(正如我在之前的问题中提到的那样)。现在 countItem() 在每个事件上触发,例如与页面滚动。如果有 10 个项目要显示,它会随着页面的滚动而上升和上升。还有 NG0100:ExpressionChangedAfterItHasBeenCheckedError 在每个触发器上抛出。
    • 您是否可以添加整个代码,因为很难用这篇文章给出深入的答案。
    • 更新了答案,现在可以查看了。
    【解决方案3】:

    我会做这样的事情: 为 JSON 创建接口

    export interface ListItem {
      id: number;
      count: number;
      title: string;
    }
    

    并在你的 component.ts 中使用它:

    @Component({selector: 'app-list', changeDetection: ChangeDetection.OnPush})
    export class ListComponent {
      @Input() items?: ListItem [] | null; // with ? and | null your component will work with async pipe and strict TypeScript
    }
    

    你的ListComponenthtml:

    <p *ngIf="items?.length">{{items.length}} items displayed!</p>
    <p *ngIf="!items?.length">Nothing to display!</p>
    
    <ol> // It's always better to use native html element.
      <li *ngFor="let item of items">{{item.title}}</li>
    </ol>
    

    创建一个执行所有逻辑的Angular pipe

    @Pipe({name: 'countFilter'})
    export class CountFilterPipe implements PipeTransform{
      transform(value: ListItem[] | null | undefined) { // with the above logic mark null | undefined too.
        if(!value) {
          return;
        }
        return value.filter(item => item => item.count < 100);
      }
    }
    

    您的AppComponent 或您使用app-list 的任何html 组件:

    <app-list [items]="items | countFilter"></app-list>
    

    【讨论】:

      猜你喜欢
      • 2022-10-15
      • 1970-01-01
      • 1970-01-01
      • 2017-12-10
      • 2019-05-17
      • 1970-01-01
      • 2020-03-22
      • 1970-01-01
      • 2020-10-23
      相关资源
      最近更新 更多