我有一个ngFor在表中创建过滤和分页的行。
<tr *ngFor="#d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
页面上还有另一个元素显示显示的记录数。这些元素最初绑定到数据。结果&#39;长度。
如何获取应用过滤器管道后显示的数据长度,以便我可以正确显示它。 ngFor中提供的局部变量似乎都没有考虑到这一点。
答案 0 :(得分:13)
一种方法是使用@ViewChildren()
<tr #myVar *ngFor="let d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
@ViewChildren('myVar') createdItems;
ngAfterViewInit() {
console.log(this.createdItems.toArray().length);
}
答案 1 :(得分: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
}
});
}
}
以下是如何使用它:
<tr *ngFor="#d of data.results |
filter:filterText |
pagination:resultsPerPage:currentPage |
withParent">
Count: {{d.parent.length }}
Item: {{ d.item.name}}
</tr>
答案 2 :(得分:7)
这不是原始问题的目的,但我也在寻找一种方法来显示所有管道应用后的项目数。通过组合ngFor提供的索引和最后一个值,我发现了另一个解决方案:
<div *ngFor="#item of (items | filter); #i = index; #last = last">
...
<div id="counter_id" *ngIf="last">{{index + 1}} results</div>
</div>
答案 3 :(得分:6)
我找到了最简单的解决方案:
filterMetadata = { count: 0 };
<tr *ngFor="#d of data.results | filter:filterText:filterMetadata | pagination:resultsPerPage:currentPage">
<span> {{filterMetadata.count}} records displayed</span>
transform(items, ..., filterMetadata) {
// filtering
let filteredItems = filter(items);
filterMetadata.count = filteredItems.length;
return filteredItems;
}
此解决方案仍使用纯管道,因此不会出现性能下降。 如果您有多个管道进行过滤,则应将filterMetadata作为参数添加到所有管道,因为一旦管道返回空数组,角度就会停止调用管道序列,因此您无法将其添加到第一个或最后一个过滤管。
答案 4 :(得分: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;
}
然后,在模板中:
<ul>
<li *ngFor="let el of filter()">
{{ el | json }}
</li>
</ul>
// mycomponent.component.html
<p > There are {{ filteredLength }} element(s) in this page</p>
除非您真的想使用Pipes
,否则我建议您在上述示例中避免使用它们。
答案 5 :(得分:4)
所以我找到了解决方法。
我创建了一个管道,它接受一个对象引用并使用当前通过管道的计数更新一个属性。
@Pipe({
name: 'count'
})
export class CountPipe implements PipeTransform {
transform(value, args) {
if (!args) {
return value;
}else if (typeof args === "object"){
//Update specified object key with count being passed through
args.object[args.key] = value.length;
return value;
}else{
return value;
}
}
}
然后在你的视图中链接一个像这样的分页组件。
pagination-controls(#controls="", [items]="items.length", (onChange)="o")
tbody
tr(*ngFor=`let item of items
| filter_pipe: { .... }
| count: { object: controls , key: 'items' }
| pagination_pipe: { ... } `)
一旦将count属性从管道中提取到当前组件或子组件,您就可以对它执行任何操作。
答案 6 :(得分:0)
在我的情况下,我需要运行已过滤的元素并运行一些分析。
我的解决方案是简单地传递一个函数并在最后一个管道上返回数组。您也可以为此创建一个管道,但我已将其添加到过滤器中的最后一个管道:
HTML
<divclass="card" *ngFor="let job of jobs | employee:jobFilter.selectedEmployee | managerStatus:jobFilter.selectedStatus | dateOrder:jobFilter">
组件
this.jobFilter = {
jobStatuses: {}, // status labels
ordering: 'asc',
selectedEmployee: {},
selectedStatus: {}, // results status
fn: this.parseFilteredArr
};
parseFilteredArr(arr) {
console.log(arr);
}
管
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'dateOrder'
})
export class DateOrderPipe implements PipeTransform {
transform(value: any, args?: any): any {
const arr = Array.isArray(value)
? value.reverse()
: value;
args.fn(arr);
return arr;
}
}
如您所见,我已在管道中调用该功能
args.fn(ARR);
现在可以在控制器中处理它。
答案 7 :(得分:0)
假设您的ngFor看起来像:
<div #cardHolder>
<app-card *ngFor="let card of cards|pipeA:paramX|pipeB:paramY"></app-card>
</div>
然后,您可以在组件中使用类似以下内容的
: get displayedCards() : number {
let ch = this.cardHolder.nativeElement;
// In case cardHolder has not been rendered yet...
if(!ch)
return 0;
return ch.children.length;
}
您可以通过简单的插值在视图中显示
{{displayedCards}}
优点包括不需要修改管道以返回其他数据。
答案 8 :(得分:0)
对我有用的是:
不要使用管道,几个月后,您将无法说出它们的含义,也无法弄清奇怪的语法。
框架(这里为Angular)是可以的,但在一定程度上,请保持模板简单ngFor绑定到数据数组。超出此范围意味着您将纠结于特定于框架的特殊语法和(不断变化的)机制。 (这说明了为什么我们有此帖子/问题首先不应该存在)
HTML模板用于布局,请保持原样。所有逻辑,数据过滤等都应保留在代码中,并放在简单的类中。
只需在组件或服务中创建一个筛选器方法,然后调用它来筛选您的数据。