Мне нужно реализовать бесконечную прокрутку, потому что ответ моего бэкэнда ограничен только 100 элементами. Итак, при попытке первой страницы я получаю 100 элементов из бэкэнда. И при каждой прокрутке до конца страницы мне нужно вызвать конечную точку еще для 100 элементов.
В моем дочернем компоненте (BpHistoryListInfiniteComponent
) я устанавливаю атрибут data-load
для отслеживания, когда 100. элемент появляется в поле зрения. А затем с IntersectionObserver
, установленным в Subject (pageByScroll$
) значение атрибута загрузки данных. Мое pageByScroll$
должно начинаться с 0 (для первой попытки страницы), и я использую distinct()
, потому что мне нужно distinct
уже загруженных элементов, а затем передать это значение моему родительскому компоненту.
Но после использования одного из фильтров в родительском компоненте мне нужно сбросить значение index
до 0 и отправить его и значение фильтров на серверную часть (и получить только 100 элементов), а затем, если пользователь прокрутит вниз, мне нужно снова увеличить index
с 0 но distinct()
не позволяйте мне этого.
Мне нужно как-то сбросить разные значения.
//html часть дочернего компонента
<div #infiniteScrollMadness class="column">
<div *ngFor="let item of history; let i = index" class="list" [attr.data-load]="(i + 1) % 100 == 0 ? (i + 1) : null">
<span>{{ item.id }}</span>
<span>{{ item.name }}</span>
</div>
</div>
.ts часть дочернего компонента
export class BpHistoryListInfiniteComponent implements AfterViewInit {
public pageByScroll$ = new Subject<number>();
@ViewChild("infiniteScrollMadness")
private scrollHost: ElementRef;
@Input()
history: HistoryModel;
@Input()
highlight: string;
@Output()
index = new EventEmitter<number>();
ngAfterViewInit() {
const intersectionObserver = new IntersectionObserver(
entries => {
entries
.filter(element => element.isIntersecting)
.forEach(element => {
this.pageByScroll$.next(
element.target.attributes["data-load"].value
);
});
},
{
threshold: 0.1
}
);
const mutationObserver = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (!mutation.addedNodes || mutation.type !== "childList") {
return;
}
const nodes = Array.prototype.slice.call(mutation.addedNodes, 0);
nodes.filter(node => node.nodeType === Node.ELEMENT_NODE)
.forEach((element: Element) => {
if (element.attributes["data-load"]) {
this.zone.runOutsideAngular(() => {
intersectionObserver.observe(element);
});
}
});
});
});
mutationObserver.observe(this.scrollHost.nativeElement, {
childList: true
});
this.pageByScroll$.pipe(
startWith(0),
distinct()
).subscribe(index => this.index.emit(index));
}
constructor(private zone: NgZone) {}
}
pageByScroll$
поток:
- попытка первой страницы => значение: 0
- прокрутить вниз (+100) => значение: 100
- прокрутить вниз (+100) => значение: 200
- прокрутить вниз (+100) => значение: 300
- использовать один из фильтров => значение: 0
- прокрутить вниз (+100) => значение: 100
- прокрутить вниз ( +100) => значение: 200