I have an ngFor creating rows in a table that is both filtered and paged.
<tr *ngFor="#d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
There is another element on the page that displays the number of records displayed. These elements are initially bound to the data.Results' length.
How do I get the length of the data that is displayed after the filter pipe has been applied so that I can display it correctly. None of the provided local variables in ngFor seem to account for this.
One way is to use template variables with @ViewChildren()
<tr #myVar *ngFor="let d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
@ViewChildren('myVar') createdItems;
ngAfterViewInit() {
console.log(this.createdItems.toArray().length);
}
I found the simplest solution to be the following:
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;
}
This solution still uses pure pipes, so there are no performance degradations. If you have multiple pipes that do filtering, the filterMetadata should be added as a parameter to all of them because angular stops calling the pipe sequence as soon as the a pipe returns an empty array, so you can't just add it to the first or last filtering pipe.
That is not exactly the purpose of the original question, but I was also looking for a way to display the count of items once that all pipes have been applied. By combining the index and last values provided by ngFor, I found this other solution :
<div *ngFor="#item of (items | filter); #i = index; #last = last">
...
<div id="counter_id" *ngIf="last">{{index + 1}} results</div>
</div>