Как найти количество элементов в ngFor после применения труб
У меня есть ngДля создания строк в таблице, которая отфильтрована и выгружена.
<tr *ngFor="#d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
На странице отображается еще один элемент, отображающий количество отображаемых записей. Эти элементы первоначально привязаны к данным. Длина результатов.
Как получить длину данных, которые будут отображаться после применения фильтра, чтобы я мог отображать его правильно. Ни одна из предоставленных локальных переменных в ngFor, похоже, не учитывает это.
Ответы
Ответ 1
Вы можете получить количество элементов, преобразуя массив в канал.
Идея состоит в том, что труба преобразует массив в другой массив, где каждый элемент имеет свойство элемента, а родительское свойство представляет отфильтрованный (или оригинальный) массив:
@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
Один из способов - использовать переменные шаблона с @ViewChildren()
<tr #myVar *ngFor="let d of data.results | filter:filterText | pagination:resultsPerPage:currentPage">
@ViewChildren('myVar') createdItems;
ngAfterViewInit() {
console.log(this.createdItems.toArray().length);
}
Ответ 3
Это не совсем цель исходного вопроса, но я также искал способ отображения количества элементов, когда все трубы были применены. Объединив индекс и последние значения, предоставленные ngFor, я нашел это другое решение:
<div *ngFor="#item of (items | filter); #i = index; #last = last">
...
<div id="counter_id" *ngIf="last">{{index + 1}} results</div>
</div>
Ответ 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 извлекается из канала либо к текущему компоненту, либо к дочернему компоненту, вы можете что-то с ним делать.
Ответ 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 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
, я бы рекомендовал вам избегать их в ситуациях, подобных приведенному выше примеру.
Ответ 6
В моем случае мне нужно было пройти через отфильтрованные элементы и выполнить некоторый анализ.
Мои решения - просто передать функцию и вернуть массив на последнем канале. Вы могли бы просто создать канал специально для этого, но я добавил его в свой последний канал в фильтрах:
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(обр);
и теперь может обрабатывать его в контроллере.