πŸ” Smarter Infinite Scroll in Angular with IntersectionObserver

In my previous blog, I demonstrated how to implement infinite scroll in Angular using scroll events. While that method works well, there's a cleaner and more performant approach available the IntersectionObserver API.

In this post, I’ll walk you through how to use IntersectionObserver to implement infinite scroll in Angular without relying on scroll events or calculating positions manually.


πŸš€ Why Use IntersectionObserver?

The IntersectionObserver API lets you detect when an element (called a sentinel) enters the viewport. This makes it perfect for loading more data automatically with no scroll math involved.

βœ… Benefits:

  • Browser-optimized

  • Cleaner and more declarative

  • No need for debouncing or throttle logic

  • Decoupled from scroll listeners


πŸ› οΈ Implementation in Angular

🧱 Component Setup

We'll start with a scrollable container and use a special <div> at the bottom as our sentinel element.

HTML Template:

<div class="container">
  <div *ngFor="let item of items" class="item">
    {{ item }}
  </div>

  <div *ngIf="isLoading" class="loading">Loading...</div>
  <div *ngIf="endOfData" class="end">No more items</div>

  <!-- Sentinel element -->
  <div #anchor class="sentinel" *ngIf="!endOfData"></div>
</div>

Component Code:

import { Component, ElementRef, OnDestroy, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { PaginationService } from 'src/app/services/pagination.service';

@Component({
  selector: 'app-infinite-scroll-intersection-observer',
  templateUrl: './infinite-scroll-intersection-observer.component.html',
  styleUrls: ['./infinite-scroll-intersection-observer.component.css']
})
export class InfiniteScrollIntersectionObserverComponent implements OnInit, AfterViewInit, OnDestroy {
  items: string[] = [];
  page = 1;
  pageSize = 20;
  isLoading = false;
  endOfData = false;

  @ViewChild('anchor', { static: false }) anchor!: ElementRef;
  private observer!: IntersectionObserver;

  constructor(private paginationService: PaginationService) {}

  ngOnInit() {
    this.loadItems();
  }

  ngAfterViewInit() {
    this.setupIntersectionObserver();
  }

  ngOnDestroy() {
    if (this.observer) {
      this.observer.disconnect();
    }
  }

  private setupIntersectionObserver() {
    const options = {
      root: null, // observes viewport
      threshold: 0.1
    };

    this.observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting && !this.isLoading && !this.endOfData) {
        this.loadItems();
      }
    }, options);

    if (this.anchor) {
      this.observer.observe(this.anchor.nativeElement);
    }
  }

  loadItems() {
    if (this.isLoading || this.endOfData) return;

    this.isLoading = true;

    this.paginationService.getItems(this.page, this.pageSize).subscribe(data => {
      if (data.length === 0) {
        this.endOfData = true;
        this.observer.disconnect(); // Optional: stop observing
      } else {
        this.items.push(...data);
        this.page++;
      }

      this.isLoading = false;
    });
  }
}

πŸ’… Styling Tips

Make sure your container is scrollable and your sentinel is visible to the observer:

.container {
  height: 400px;
  overflow-y: auto;
}
.sentinel {
  height: 1px;
}
.loading, .end {
  text-align: center;
  padding: 10px;
}

πŸ” Backend Note

πŸ’‘ Note: The backend API (pagination service) used in this example is the same as in my previous blog post on Infinite Scroll with Angular and .NET Core API.
If you're looking for how the data is fetched or how the pagination service is set up, please refer to the earlier post here.


βœ… Summary

Using IntersectionObserver:

  • Makes infinite scroll cleaner and more efficient

  • Lets the browser handle intersection logic instead of manual calculations

  • Reduces complexity in your code


πŸ’¬ Final Thought

If you’re building Angular apps that fetch data as the user scrolls, I highly recommend giving IntersectionObserver a try.

➑️ Already implemented it?
➑️ Prefer scroll event listeners instead?

Let me know what worked for you!


0
Subscribe to my newsletter

Read articles from Pranali Kulkarni directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Pranali Kulkarni
Pranali Kulkarni