Angular VirtualScroller

Angular VirtualScroller

·

3 min read

Angular VirtualScroller is an efficient way of rendering lists by displaying a small subset of data in the viewport at any time.

CDK

VirtualScrolling depends on @angular/cdk's ScrollingModule so begin with installing CDK if not already installed.

npm install @angular/cdk --save

Setup

Refer to PrimeNG setup documentation for download and installation steps for your environment.

Import

import {VirtualScrollerModule} from 'primeng/virtualscroller';

Getting Started

VirtualScroller requires a collection of items as its value, height of an item size, height of the scrollable viewport and a ng-template to display where each item can be accessed using the implicit variable.

Throughout the samples, a car interface having vin, brand, year and color properties are used to define an object to be displayed by the VirtualScroller. Cars are loaded by a CarService that connects to a server to fetch the cars with a Promise. Note that this is for demo purposes only, any data source such as an Observable can be used as an alternative as well.

export interface Car {
    vin;
    year;
    brand;
    color;
}
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { Car } from '../domain/car';

@Injectable()
export class CarService {

    constructor(private http: HttpClient) {}

    getCarsSmall() {
        return this.http.get('/showcase/resources/data/cars-small.json')
                    .toPromise()
                    .then(res => <Car[]> res.data)
                    .then(data => { return data; });
    }
}

Here is a sample VirtualScroller that displays a list of cars loaded from a remote datasource.

export class VirtualScrollerDemo implements OnInit {

    cars: Car[];

    constructor(private carService: CarService) { }

    ngOnInit() {
        this.carService.getCarsLarge().then(cars => this.cars = cars);
    }
}
<p-virtualScroller [value]="cars" scrollHeight="500px" [itemSize]="150">
    <ng-template pTemplate="item" let-car>
        Car content
    </ng-template>
</p-virtualScroller>

Sections

Header and Footer are the two sections that are capable of displaying custom content.

<p-virtualScroller [value]="cars" scrollHeight="500px" [itemSize]="150">
    <ng-template pTemplate="header">Header Content</ng-template>
    <ng-template pTemplate="item" let-car>
    Car content
    </ng-template>
    <ng-template pTemplate="footer">Footer Content</ng-template>
</p-virtualScroller>

Lazy Loading

Lazy mode is handy to deal with large datasets where instead of loading the entire data, small chunks of data are loaded on demand by invoking onLazyLoad callback everytime scrolling requires a new chunk. To implement lazy loading, enable lazy attribute, initialize your data as a placeholder with a length and finally implement a method callback using onLazyLoad that actually loads a chunk from a datasource. onLazyLoad gets an event object that contains information about the chunk of data to load such as the index and number of items to load. Notice that a new template called loadingItem is also required to display as a placeholder while the new items are being loaded.

<p-virtualScroller [value]="virtualCars" scrollHeight="500px" [itemSize]="150" [rows]="100"
    [lazy]="true" (onLazyLoad)="loadCarsLazy($event)">
    <ng-template let-car pTemplate="item">
        Car content
    </ng-template>
    <ng-template let-car pTemplate="loadingItem">
        Loading...
    </ng-template>
</p-virtualScroller>
export class LazyVirtualScrollerDemo implements OnInit {

    virtualCars: Car[];

    ngOnInit() {
        this.cars = Array.from({length: 10000}).map(() => this.carService.generateCar());
        this.virtualCars =  Array.from({length: 10000});
    }

    loadCarsLazy(event: LazyLoadEvent) {       
        //simulate remote connection with a timeout 
        setTimeout(() => {
            //load data of required page
            let loadedCars = this.cars.slice(event.first, (event.first + event.rows));

            //populate page of virtual cars
            Array.prototype.splice.apply(this.virtualCars, [...[event.first, event.rows], ...loadedCars]);

            //trigger change detection
            this.virtualCars = [...this.virtualCars];
        }, 1000);
    }

}

Programmatic Scroll

Scrolling to a specific index can be done with the scrollToIndex function.

<button pButton label="Reset" (click)="reset"></button>

<p-virtualScroller #vs [value]="cars" scrollHeight="500px" [itemSize]="150">
    <ng-template pTemplate="item" let-car>
        Car content
    </ng-template>
</p-virtualScroller>
@ViewChild('vs') vs: VirtualScroller;

reset() {
    this.vs.scrollToIndex(0, 'smooth');
}

Theming

VirtualScroller supports various themes featuring Material, Bootstrap, Fluent as well as your own custom themes via the Designer tool.

Resources

Visit the PrimeNG VirtualScroller showcase for demos and documentation.