Компоненты PrimeNG
VirtualScroller

Виртуальный Скроллер

PrimeNG/VirtualScroller (opens in a new tab)

Виртуальный скроллер - это эффективный способ отображения списков путем отображения небольшого подмножества данных в окне просмотра в любое время.

С чего начать

Подключите модуль

import { VirtualScrollerModule } from 'primeng/virtualscroller';

В .ts файле

import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { LazyLoadEvent, SelectItem } from 'primeng/api';
 
export interface Product {
  id?: string;
  code?: string;
  name?: string;
  description?: string;
  price?: number;
  quantity?: number;
  inventoryStatus?: string;
  category?: string;
  image?: string;
  rating?: number;
}
 
@Component({
  selector: 'app-prime-virtualscroller',
  templateUrl: './prime-virtualscroller.component.html',
  styleUrls: ['./prime-virtualscroller.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PrimeVirtualscrollerComponent implements OnInit {
  products: Product[];
  virtualProducts: Product[];
  sortKey = '';
  sortOptions: SelectItem[] = [];
 
  status: string[] = ['OUTOFSTOCK', 'INSTOCK', 'LOWSTOCK'];
 
  productNames: string[] = [
    'Bamboo Watch',
    'Black Watch',
    'Blue Band',
    'Blue T-Shirt',
    'Bracelet',
    'Brown Purse',
    'Chakra Bracelet',
    'Galaxy Earrings',
    'Game Controller',
    'Gaming Set',
    'Gold Phone Case',
    'Green Earbuds',
    'Green T-Shirt',
    'Grey T-Shirt',
    'Headphones',
    'Light Green T-Shirt',
    'Lime Band',
    'Mini Speakers',
    'Painted Phone Case',
    'Pink Band',
    'Pink Purse',
    'Purple Band',
    'Purple Gemstone Necklace',
    'Purple T-Shirt',
    'Shoes',
    'Sneakers',
    'Teal T-Shirt',
    'Yellow Earbuds',
    'Yoga Mat',
    'Yoga Set',
  ];
 
  constructor() {}
 
  ngOnInit(): void {
    this.products = Array.from({ length: 10000 }).map(() => this.generateProduct());
 
    this.sortOptions = [
      { label: 'Cheapest First', value: 'price' },
      { label: 'Expensive First', value: '!price' },
    ];
  }
 
  generateProduct(): Product {
    const product: Product = {
      id: this.generateId(),
      name: this.generateName(),
      description: 'Product Description',
      price: this.generatePrice(),
      quantity: this.generateQuantity(),
      category: 'Product Category',
      inventoryStatus: this.generateStatus(),
      rating: this.generateRating(),
    };
 
    return product;
  }
 
  generateId() {
    let text = '';
    let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
 
    for (var i = 0; i < 5; i++) {
      text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
 
    return text;
  }
 
  generateName() {
    return this.productNames[Math.floor(Math.random() * Math.floor(30))];
  }
 
  generatePrice() {
    return Math.floor(Math.random() * Math.floor(299) + 1);
  }
 
  generateQuantity() {
    return Math.floor(Math.random() * Math.floor(75) + 1);
  }
 
  generateStatus() {
    return this.status[Math.floor(Math.random() * Math.floor(3))];
  }
 
  generateRating() {
    return Math.floor(Math.random() * Math.floor(5) + 1);
  }
 
  loadCarsLazy(event: LazyLoadEvent) {
    // simulate remote connection with a timeout
    setTimeout(() => {
      //load data of required page
      let loadedProducts = this.products.slice(event.first, event.first + event.rows);
 
      //populate page of virtual cars
      Array.prototype.splice.apply(this.virtualProducts, [...[event.first, event.rows], ...loadedProducts]);
 
      //trigger change detection
      this.virtualProducts = [...this.virtualProducts];
    }, 1000);
  }
 
  onSortChange() {
    if (this.sortKey.indexOf('!') === 0) this.sort(-1);
    else this.sort(1);
  }
 
  sort(order: number): void {
    let products = [...this.products];
    products.sort((data1, data2) => {
      let value1 = data1.price;
      let value2 = data2.price;
      let result = value1 < value2 ? -1 : value1 > value2 ? 1 : 0;
 
      return order * result;
    });
 
    this.products = products;
  }
}

Встройте компонент с помощью тэга p-virtualScroller.

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

Lazy Loading

[rows]для указания размера пагинации больше не поддерживается, расчет количества строк идет автоматически, получить значение можно вevent.rowsсобытияonLazyLoad

По дефолтуpTemplate="loadingItem"не используется, требуется включить черезoptions.showLoader: true

Для оптимизации рендера рекомендуется использовать функциюtrackBy. По уникальному ключу (id).Через options.trackBy

List of Products

product.name

product.category

$ product.price

product.inventoryStatus

{{codeExamples.virtualScrollerHTMLExample}}

Prepopulated List

List of Products

product.name

product.category

$ product.price

product.inventoryStatus

Свойства

NameTypeDefaultDescription
delaynumber250Threshold in milliseconds to delay lazy loading during scrolling.
itemSizenumbernullHeight of an item in the list.
lazybooleanfalseDefines if data is loaded and interacted with in lazy manner.
minBufferPxnumbernullMinimum amount of content buffer (in pixels) that the viewport must render.
maxBufferPxnumbernullConfigures how much buffer space to render back up to when it detects that more buffer is required.
scrollHeightanynullMax height of the content area in inline mode.
stylestringnullInline style of the component.
styleClassstringnullStyle class of the component.
valuearraynullAn array of objects to display.

Конфигурация через свойство [options]

Посмотреть все свойства и методы можно в интерфейсеScrollerOptions

NameTypeDefaultDescription
trackByfunctionnullFunction to optimize the dom operations by delegating to ngForTrackBy, default algorithm checks for object identity.
showLoaderbooleanfalseЗаменять пустые итемы в списке, во время события загрузки, другим темплейтом
loadingbooleanfalseПоказывать перекрывающий темплейт во время загрузки

События

NameParametersDescription
onLazyLoadevent.first = First row offset<br>event.rows = Number of rows per page<br>Callback to invoke in lazy mode to load new data.

Методы

NameParametersDescription
scrollToIndexindex: Index of the item.<br>mode: Scroll mode e.g. 'auto' or 'smooth'Scrolls to the item with the given index.

Шаблоны

NameParameters
header-
item$implicit: Data of the option<br>index: Index of the option<br>count: Count of the options<br>first: First row offset<br>last: Last row offset
loadingItem$implicit: Data of the option<br>index: Index of the option<br>count: Count of the options<br>first: First row offset<br>last: Last row offset
footer-

Стилизация

NameElement
p-virtualscrollerContainer element.
p-virtualscroller-headerHeader section.
p-virtualscroller-footerFooter section.
p-virtualscroller-contentContent section.
p-virtualscroller-listList element.