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

    Import

    1. import {VirtualScrollerModule} from 'primeng/virtualscroller';
    2.  

    Getting Started

    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.

    1. export interface Car {
    2. vin;
    3. year;
    4. brand;
    5. color;
    6. }
    7.  

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

    1. export class VirtualScrollerDemo implements OnInit {
    2. cars: Car[];
    3. constructor(private carService: CarService) { }
    4. ngOnInit() {
    5. this.carService.getCarsLarge().then(cars => this.cars = cars);
    6. }
    7. }
    8.  
    1. <p-virtualScroller [value]="cars" scrollHeight="500px" [itemSize]="150">
    2. <ng-template pTemplate="item" let-car>
    3. Car content
    4. </ng-template>
    5. </p-virtualScroller>
    6.  

    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 the number of logical rows with a query 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.

    1. <p-virtualScroller [value]="lazyCars" scrollHeight="500px" [itemSize]="150" [rows]="100" [cache]="false"
    2. [lazy]="true" (onLazyLoad)="loadCarsLazy($event)" [totalRecords]="totalLazyCarsLength">
    3. <ng-template let-car pTemplate="item">
    4. Car content
    5. </ng-template>
    6. <ng-template let-car pTemplate="loadingItem">
    7. Loading...
    8. </ng-template>
    9. </p-virtualScroller>
    10.  
    1. loadData(event) {
    2. //event.first = First row offset
    3. //event.rows = Number of rows per page
    4. //this.lazyCars = load new chunk between first index and (first + rows) last index
    5. }
    6.  

    Properties

    Methods

    Styling

    Following is the list of structural style classes, for theming classes visit theming page.

    Source

    View on GitHub

    1. @Component({
    2. templateUrl: './virtualscrollerdemo.html',
    3. styles: [`
    4. .car-item .ui-md-3 {
    5. text-align: center;
    6. }
    7. .car-item .ui-g-10 {
    8. font-weight: bold;
    9. }
    10. .empty-car-item-index {
    11. background-color: #f1f1f1;
    12. height: 60px;
    13. margin: 36px auto 0 auto;
    14. animation: pulse 1s infinite ease-in-out;
    15. }
    16. .empty-car-item-image {
    17. background-color: #f1f1f1;
    18. width: 120px;
    19. height: 120px;
    20. animation: pulse 1s infinite ease-in-out;
    21. .empty-car-item-text {
    22. background-color: #f1f1f1;
    23. height: 18px;
    24. animation: pulse 1s infinite ease-in-out;
    25. }
    26. .title-container {
    27. padding: 1em;
    28. text-align: right;
    29. }
    30. .sort-container {
    31. text-align: left;
    32. }
    33. @media (max-width: 40em) {
    34. .car-item {
    35. text-align: center;
    36. }
    37. }
    38. `]
    39. })
    40. export class VirtualScrollerDemo implements OnInit {
    41. cars: Car[] = [];
    42. lazyCars: Car[];
    43. brands: string[];
    44. colors: string[];
    45. totalLazyCarsLength: number;
    46. timeout: any;
    47. sortKey: string;
    48. sortOptions: SelectItem[];
    49. constructor(private carService: CarService) { }
    50. ngOnInit() {
    51. this.brands = [
    52. 'Audi', 'BMW', 'Fiat', 'Ford', 'Honda', 'Jaguar', 'Mercedes', 'Renault', 'Volvo', 'VW'
    53. ];
    54. this.colors = [
    55. 'Black', 'White', 'Red', 'Blue', 'Silver', 'Green', 'Yellow'
    56. ];
    57. for (let i = 0; i < 10000; i++) {
    58. this.cars.push(this.generateCar());
    59. }
    60. //in a real application, make a remote request to retrieve the number of records only, not the actual records
    61. this.totalLazyCarsLength = 10000;
    62. this.sortOptions = [
    63. {label: 'Newest First', value: '!year'},
    64. {label: 'Oldest First', value: 'year'}
    65. }
    66. generateCar(): Car {
    67. vin: this.generateVin(),
    68. brand: this.generateBrand(),
    69. color: this.generateColor(),
    70. year: this.generateYear()
    71. }
    72. }
    73. generateVin() {
    74. let text = "";
    75. let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    76. for (var i = 0; i < 5; i++) {
    77. text += possible.charAt(Math.floor(Math.random() * possible.length));
    78. }
    79. return text;
    80. }
    81. generateBrand() {
    82. return this.brands[Math.floor(Math.random() * Math.floor(10))];
    83. }
    84. generateColor() {
    85. return this.colors[Math.floor(Math.random() * Math.floor(7))];
    86. }
    87. generateYear() {
    88. return 2000 + Math.floor(Math.random() * Math.floor(19));
    89. }
    90. loadCarsLazy(event: LazyLoadEvent) {
    91. //in a real application, make a remote request to load data using state metadata from event
    92. //event.first = First row offset
    93. //event.rows = Number of rows per page
    94. //imitate db connection over a network
    95. if (this.timeout) {
    96. clearTimeout(this.timeout);
    97. }
    98. this.timeout = setTimeout(() => {
    99. this.lazyCars = [];
    100. if (this.cars) {
    101. this.lazyCars = this.cars.slice(event.first, (event.first + event.rows));
    102. }
    103. }, 1000);
    104. }
    105. onSortChange() {
    106. if (this.sortKey.indexOf('!') === 0)
    107. this.sort(-1);
    108. else
    109. this.sort(1);
    110. }
    111. sort(order: number): void {
    112. let cars = [...this.cars];
    113. cars.sort((data1, data2) => {
    114. let value1 = data1.year;
    115. let value2 = data2.year;
    116. let result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;
    117. return (order * result);
    118. });
    119. this.cars = cars;
    120. }
    121.