I'm working on an Angular project. I implemented an "infinite scroll" list utilizing IntersectionObvserver. Generally it works quite well and satisfying.
The entries to build the list are being sorted ascending.
In Angular this causes the problem that the HTML list is built upwards while the scrollbar remains at the same position that triggered the infinite scroll event, which causes the event to fire over and over and over again until the user scrolls away manually.
That the event is being fired as long as the infinite scroll trigger is in the viewport is desired behavior, because depending on the viewport height and user preferences it can't be guaranteed that there will always be enough items to fill the whole page initially. New items must be loaded continously until the page is filled.
https://stackblitz.com/edit/angular-infinite-scroll-intersectionobserver
Scroll to the very end of the list to trigger the infinite scroll event. It will keep the scrollbar at the same position and firing the event while building the list upwards.
In the generateItems()
function there is a call to sortItems()
. When you disable this call the scrolling behavior of the infinite scroll list works properly. New items added to the list cause the list to grow and push the infinite scroll trigger out of the viewport.
When I implement the same infinite scroll logic using native JavaScript
with jQuery
it works as expected, even when the results are sorted.
https://codepen.io/mw-108/pen/ExqPKmG
Here the infinite scroll trigger is always pushed out of the viewport when the list is updated. This is what I expect.
Am I doing something wrong in Angular?
What can I do to reproduce the same result I see in the JavaScript / jQuery example in Angular?
I am not sure why it is working on the jQuery but I actually found the problem and a solution for that. the issue is happening because the sortItems
function is directly modifying the original array and it is re-rendering the whole array in template.
So instead I modified the sorting function as below, what is does is that it return a cloned copy to the original array and reassigns it (instead of modifying it).
private sortItems() {
return this.items.slice(0).sort((a, b) => a.index - b.index);
}
If you want more information on mutation you can refer this answer