Implementing Virtual and Infinite Scroll
1. Creating Virtual Scroll
| Property | Description | Default | Notes |
|---|---|---|---|
| ionVirtualScroll | Directive to enable virtual scrolling on a list | undefined | Must be applied to ion-list or ion-content |
| items | Array of items to render in the virtual scroll | undefined | Required property for virtual scroll |
| approxItemHeight | Approximate height of each item in pixels | 40px | Improves performance by estimating item heights |
| headerFn | Function to generate header for groups | undefined | Used with grouped data |
| footerFn | Function to generate footer for groups | undefined | Used with grouped data |
Example: Basic Virtual Scroll Implementation
import { Component } from '@angular/core';
@Component({
selector: 'app-virtual-scroll',
template: '<ion-content>
<ion-list>
<ion-item *ionVirtualScroll="let item of items">
<div>{{ item.name }}</div>
</ion-item>
</ion-list>
</ion-content>'
})
export class VirtualScrollPage {
items = Array.from({ length: 1000 }, (_, i) => ({
name: `Item ${i + 1}`
}));
}
Example: Virtual Scroll with Approximate Item Height
import { Component } from '@angular/core';
@Component({
selector: 'app-virtual-scroll',
template: '<ion-content>
<ion-list>
<ion-item *ionVirtualScroll="let item of items" [approxItemHeight]="60">
<div>{{ item.name }} - {{ item.description }}</div>
</ion-item>
</ion-list>
</ion-content>'
})
export class VirtualScrollPage {
items = Array.from({ length: 1000 }, (_, i) => ({
name: `Item ${i + 1}`,
description: `Description for item ${i + 1}`
}));
}
Note: Virtual scroll is particularly useful for large lists where performance is a concern. It only renders items that are currently visible in the viewport, significantly reducing DOM overhead.
2. Configuring Virtual Scroll
| Property | Values | Description |
|---|---|---|
| ionVirtualScroll | boolean |
Enables virtual scrolling on the component. Default is false. |
| approxItemHeight | number |
Approximate height of each item in pixels. Used for calculating the number of items to render. |
| headerFn | (index: number) => string |
Function to generate header content for groups of items. |
| footerFn | (index: number) => string |
Function to generate footer content for groups of items. |
Example: Basic Virtual Scroll Configuration
<ion-list>
<ionVirtualScroll approxItemHeight="100">
<ion-item *virtualItem="let item">
<ion-label>{{ item.name }}</ion-label>
</ion-item>
</ionVirtualScroll>
</ion-list>
Note: The
approxItemHeight property is crucial for performance. If set incorrectly, it can lead to rendering issues or excessive memory usage.
3. Implementing Infinite Scroll
Example: Basic Infinite Scroll Implementation
import { Component } from '@angular/core';
@Component({
selector: 'app-infinite-scroll',
template: '<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
{{ item }}
</ion-item>
</ion-list>
<ion-infinite-scroll (ionInfinite)="loadData($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>'
})
export class InfiniteScrollComponent {
items = [];
loadData(event) {
for (let i = 0; i < 50; i++) {
this.items.push(`Item ${this.items.length + 1}`);
}
event.target.complete();
}
}
| Property | Values | Description |
|---|---|---|
| ionInfinite | (ionInfinite) |
Event emitted when the infinite scroll reaches the end |
| complete() | void |
Method to call when data loading is complete |
| disabled | boolean |
Disables the infinite scroll if true |
Note: The
complete() method must be called to signal that new data has been loaded and the scroll is ready for more data.
Example: Infinite Scroll with Loading State
import { Component } from '@angular/core';
@Component({
selector: 'app-infinite-scroll',
template: '<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
{{ item }}
</ion-item>
</ion-list>
<ion-infinite-scroll (ionInfinite)="loadMore($event)">
<ion-infinite-scroll-content
loadingSpinner="dots"
loadingText="Loading more data...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>'
})
export class InfiniteScrollComponent {
items = [];
loading = false;
loadMore(event) {
this.loading = true;
setTimeout(() => {
for (let i = 0; i < 20; i++) {
this.items.push(`Item ${this.items.length + 1}`);
}
event.target.complete();
this.loading = false;
}, 1000);
}
}
4. Using Infinite Scroll Content
| Property | Description | Values |
|---|---|---|
| ion-infinite-scroll | Component to implement infinite scroll | <ion-infinite-scroll> |
| ion-infinite-scroll-content | Content to display during infinite scroll | <ion-infinite-scroll-content> |
| position | Position of the infinite scroll content | 'top', 'bottom' |
| spinner | Spinner to display during loading | 'bubbles', 'circles', 'crescent', 'dots', 'lines', 'lines-sharp', 'lines-small', 'lines-small-sharp', 'none' |
| loadingText | Text to display during loading | string |
Example: Basic Infinite Scroll Content
<ion-infinite-scroll>
<ion-infinite-scroll-content
loadingText="Loading more data..."
spinner="bubbles">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
Example: Infinite Scroll with Custom Spinner
<ion-infinite-scroll>
<ion-infinite-scroll-content
loadingText="Loading more items..."
spinner="lines">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
Note: The
ion-infinite-scroll-content component is used to define the content that appears during infinite scroll operations. It supports various spinner types and custom loading text.
5. Handling Infinite Event
| Property | Description | Values |
|---|---|---|
| ionInfiniteScroll | Event emitted when the infinite scroll reaches the end of the content | true to enable infinite scroll |
| ionInfinite | Handler function for the infinite scroll event | Function that returns a Promise or void |
Example: Handling Infinite Scroll Event
import { Component, ViewChild } from '@angular/core';
import { IonInfiniteScroll } from '@ionic/angular';
@Component({
selector: 'app-infinite-scroll',
template: '<ion-content>' +
'<ion-list>' +
'<ion-item *ngFor="let item of items">{{ item }}</ion-item>' +
'</ion-list>' +
'<ion-infinite-scroll (ionInfinite)="loadData($event)">' +
'<ion-infinite-scroll-content></ion-infinite-scroll-content>' +
'</ion-infinite-scroll>' +
'</ion-content>'
})
export class InfiniteScrollPage {
@ViewChild(IonInfiniteScroll) infiniteScroll: IonInfiniteScroll;
items = [];
loadData(event) {
setTimeout(() => {
const newItems = Array.from({ length: 10 }, (_, i) =>
`Item ${this.items.length + i + 1}`
);
this.items.push(...newItems);
event.target.complete();
if (this.items.length >= 100) {
event.target.disabled = true;
}
}, 500);
}
}
Note: The
event.target.complete() must be called to signal that the loading is done and the scroll can continue.
Warning: If
event.target.disabled = true is not set, the infinite scroll will keep firing events even after all items are loaded.
6. Disabling Infinite Scroll
| Property | Values | Description |
|---|---|---|
| disabled | false | true |
Disables the infinite scroll functionality when set to true. |
Example: Disabling Infinite Scroll
<ion-infinite-scroll [disabled]="isDisabled">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Example: Toggle Infinite Scroll
export class MyComponent {
isDisabled = false;
toggleInfiniteScroll() {
this.isDisabled = !this.isDisabled;
}
}
7. Completing Infinite Scroll
Example: Marking Infinite Scroll as Complete
component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-infinite-scroll',
templateUrl: './infinite-scroll.component.html'
})
export class InfiniteScrollComponent implements OnInit {
items: string[] = [];
constructor() { }
ngOnInit() {
this.loadItems();
}
loadItems() {
// Simulate API call
setTimeout(() => {
const newItems = Array.from({ length: 20 }, (_, i) => `Item ${this.items.length + i + 1}`);
this.items.push(...newItems);
}, 1000);
}
async completeInfiniteScroll(event: any) {
await this.loadItems();
event.target.complete(); // Mark scroll as complete
}
}
| Method | Description | Usage |
|---|---|---|
| event.target.complete() | Signals that the infinite scroll has finished loading data | Call after new items are added to the list |
| event.target.disabled = true | Disables the infinite scroll functionality | Use when all data has been loaded |
Note: Always call
event.target.complete() to prevent duplicate loading of data.Warning: If
complete() is not called, the scroll will continue to trigger load events even when no more data is available.8. Setting Scroll Threshold
| Property | Values | Description |
|---|---|---|
| threshold | 100px, 10% |
Distance from the bottom of the scroll container to trigger infinite scroll |
Example: Setting Scroll Threshold
<ion-infinite-scroll threshold="10%">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Note: The threshold can be specified as a pixel value or percentage of the scroll container's height.
9. Using Loading Spinner
| Property | Description | Default | Notes |
|---|---|---|---|
| loadingSpinner | Spinner type to display | 'crescent' |
Options: 'bubbles', 'circles', 'crescent', 'dots', 'lines', 'pause', 'pointer', 'ripple', 'spiral' |
| loadingSpinnerColor | Color of the spinner | 'primary' |
Any valid CSS color or Ionic color name |
Example: Configuring Loading Spinner
import { Component } from '@angular/core';
@Component({
selector: 'app-infinite-scroll',
template: '<ion-content>
<ion-list>
<ion-item *ngFor="let item of items">
{{ item }}
</ion-item>
</ion-list>
<ion-infinite-scroll (ionInfinite)="loadData($event)">
<ion-infinite-scroll-content
loadingSpinner="dots"
loadingSpinnerColor="secondary">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
</ion-content>'
})
export class InfiniteScrollComponent {
items = [];
loadData(event) {
setTimeout(() => {
for (let i = 0; i < 50; i++) {
this.items.push(`Item ${this.items.length + 1}`);
}
event.target.complete();
}, 500);
}
}
Note: The
loadingSpinner property can be customized to match the app's theme or provide visual feedback during data loading. The loadingSpinnerColor allows for consistent color integration with the app's design system.
10. Positioning Infinite Scroll
| Property | Values | Description |
|---|---|---|
| position | "top" | "bottom" |
Sets the position of the infinite scroll listener. Default is "bottom". |
| distance | "10%" | "50px" |
Defines how far from the edge of the scroll container the listener should trigger. Default is "10%". |
Example: Setting Position to Top
<ion-infinite-scroll position="top">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Note: When
position is set to "top", the scroll listener will trigger when the user scrolls near the top of the content.