Coding exercise: implement infinite scrolling in Angular.
Model answer
Watch a sentinel element at the end of the list with IntersectionObserver and load the next page when it appears. Clean up the observer when the component is destroyed.
@Component({
selector: 'app-feed',
template: `
<ul>@for (x of items(); track x.id) { <li>{{ x.title }}</li> }</ul>
<div #end>{{ busy() ? 'Loading…' : done() ? 'No more items.' : '' }}</div>`,
})
export class Feed implements AfterViewInit, OnDestroy {
private http = inject(HttpClient);
items = signal<{ id: number; title: string }[]>([]);
busy = signal(false);
done = signal(false);
private page = 0;
private io?: IntersectionObserver;
end = viewChild<ElementRef<HTMLElement>>('end');
ngAfterViewInit() {
this.load();
this.io = new IntersectionObserver(([e]) => e.isIntersecting && this.load(), { rootMargin: '200px' });
this.io.observe(this.end()!.nativeElement);
}
load() {
if (this.busy() || this.done()) return;
this.busy.set(true);
this.http.get<{ items: { id: number; title: string }[] }>('/api/posts', { params: { page: ++this.page, limit: 20 } }).subscribe({
next: (d) => { this.items.update((l) => [...l, ...d.items]); if (d.items.length < 20) this.done.set(true); this.busy.set(false); },
error: () => this.busy.set(false),
});
}
ngOnDestroy() { this.io?.disconnect(); }
}Trade-offs to mention: offer a "Load more" button for keyboard users, and use the CDK virtual scroll for very long lists.
Tips
- The busy flag stops the same page being requested twice.
Practise it yourself in the React and Angular code playground.
Learn this topic
Angular Tutorial: Beginner to Advanced .
Sign in to add your own answer.
More questions
- Coding exercise: build a Todo application in Angular.
- Coding exercise: create a search box with debounce in Angular.
- Coding exercise: fetch API data and display it in a table in Angular.
- Coding exercise: implement pagination in Angular.
- Coding exercise: create a login form with validation in Angular.
- Coding exercise: build a parent-child communication example in Angular.