如何在应用管道后查找ngFor中的项目数

gha*_*kes 21 angular2-directives angular

我有一个ngFor在表中创建行,过滤和分页.

<tr *ngFor="#d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
Run Code Online (Sandbox Code Playgroud)

页面上还有另一个元素显示显示的记录数.这些元素最初绑定到data.Results的长度.

如何获取应用过滤器管道后显示的数据长度,以便我可以正确显示它.ngFor中提供的局部变量都没有考虑到这一点.

Gün*_*uer 14

一种方法是使用模板变量 @ViewChildren()

<tr #myVar *ngFor="let d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
Run Code Online (Sandbox Code Playgroud)
@ViewChildren('myVar') createdItems;

ngAfterViewInit() {
  console.log(this.createdItems.toArray().length);
}
Run Code Online (Sandbox Code Playgroud)

  • 使用此方法,您只能获取实际在DOM中创建的元素.@pixelbits方法可能更合适. (2认同)
  • 还必须使用 ngAfterViewChecked() { this.cdRef.detectChanges(); } (2认同)

jea*_*ste 8

这不是原始问题的目的,但我也在寻找一种方法来显示所有管道应用后的项目数.通过组合ngFor提供的索引和最后一个值,我找到了另一个解决方案:

<div *ngFor="#item of (items | filter); #i = index; #last = last">
...
  <div id="counter_id" *ngIf="last">{{index + 1}} results</div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 在角度4中,以下为我工作:索引为i; 最后一次 (2认同)

pix*_*its 7

您可以通过在管道中转换数组来获取项目的计数.

我们的想法是管道将数组转换为另一个数组,其中每个元素都有一个item属性,以及一个表示过滤(或原始)数组的父属性:

@Pipe({ name: 'withParent', pure: false })
export class WithParentPipe implements PipeTransform {
    transform(value: Array<any>, args: any[] = null): any {

        return value.map(t=> {
            return {
                item: t,
                parent: value
            }
        });
    }
} 
Run Code Online (Sandbox Code Playgroud)

以下是它的使用方法:

 <tr *ngFor="#d of data.results | 
        filter:filterText |
        pagination:resultsPerPage:currentPage | 
        withParent">
        Count:  {{d.parent.length }}
        Item:  {{ d.item.name}}
 </tr>
Run Code Online (Sandbox Code Playgroud)

  • @ghawkes我认为这种方法不可能.我希望angular添加一些方法来定义基于过滤的本地模板变量(类似于索引,但是自定义).还有一种方法可以指定它在迭代范围之外可用.这对于处理ngFor的一些常见用例来说是一个非常有用的功能. (2认同)

Sou*_*khi 7

我发现最简单的解决方案如下:

  1. 在您的组件中:添加一个将保存当前计数的字段
  filterMetadata = { count: 0 };
Run Code Online (Sandbox Code Playgroud)
  1. 在模板中:将filterMetadata作为参数添加到过滤器管道中
  <tr *ngFor="#d of data.results | filter:filterText:filterMetadata | pagination:resultsPerPage:currentPage">
Run Code Online (Sandbox Code Playgroud)
  1. 将filterMetadata.count插值到显示显示的记录数的元素中。
  <span> {{filterMetadata.count}} records displayed</span>
Run Code Online (Sandbox Code Playgroud)
  1. 完成过滤后,在过滤器管道中更新filterMetadata.count字段
  transform(items, ..., filterMetadata) {
    // filtering
    let filteredItems = filter(items);

    filterMetadata.count = filteredItems.length;
    return filteredItems;
  }
Run Code Online (Sandbox Code Playgroud)

该解决方案仍然使用纯管道,因此不会降低性能。如果您有多个进行过滤的管道,则应该将filterMetadata作为参数添加到所有管道中,因为一旦管道返回空数组,angular就会停止调用管道序列,因此您不能仅将其添加到第一个管道中或最后一个过滤管。


Ahm*_*Ali 5

我遇到了同样的问题,虽然@bixelbits的答案得到了批准,但我觉得它并不理想,特别是对于大数据.

我认为最好避免Pipes这个问题,至少在当前的Angular 2实现(rc4)中,不要在每个元素中返回原始数组.

更好的解决方案是使用普通组件的功能来过滤数据,如下所示:

// mycomponent.component.ts  
filter() {
  let arr = this.data.filter(
      // just an example
      item => item.toLowerCase().includes(
        // term is a local variable I get it's from <input> 
        this.term.toLowerCase()
      )
    );
  this.filteredLength = arr.length;
  return arr;
}
Run Code Online (Sandbox Code Playgroud)

然后,在模板中:

<ul>
  <li *ngFor="let el of filter()"> 
    {{ el | json }}
  </li>
</ul>
// mycomponent.component.html
<p > There are {{ filteredLength }} element(s) in this page</p>
Run Code Online (Sandbox Code Playgroud)

除非你真的想使用Pipes,否则我会建议你在上面的例子中避免使用它们.