Files
ngx-pretext-table/README.md
T
2026-04-08 23:12:46 +02:00

3.3 KiB

ngx-pretext-table

Variable-height virtual scrolling for PrimeNG p-table, powered by @chenglou/pretext.

PrimeNG's built-in virtual scroll only supports fixed row heights (virtualScrollItemSize). This library replaces it with pretext-calculated variable row heights — no DOM measurement, no layout thrashing, O(log n) scroll lookup.

Install

npm install ngx-pretext-table @chenglou/pretext

Usage

import { Component } from '@angular/core';
import { TableModule } from 'primeng/table';
import {
  PretextVirtualScrollDirective,
  PretextScrollEvent,
  PretextColumnDef,
} from 'ngx-pretext-table';

@Component({
  standalone: true,
  imports: [TableModule, PretextVirtualScrollDirective],
  template: `
    <div pretextVirtualScroll
         [data]="data"
         [columns]="columns"
         [font]="'14px system-ui'"
         [lineHeight]="20"
         [rowPadding]="16"
         [scrollHeight]="'500px'"
         (visibleRangeChange)="onRange($event)">

      <p-table [value]="visibleData" [scrollable]="false">
        <ng-template pTemplate="body" let-row let-i="rowIndex">
          <tr [style.height.px]="rowHeights[i]">
            <td>{{ row.name }}</td>
            <td>{{ row.description }}</td>
          </tr>
        </ng-template>
      </p-table>
    </div>
  `,
})
export class MyComponent {
  data = [/* your data */];

  // field + available text width (column width minus padding)
  columns: PretextColumnDef[] = [
    { field: 'name', width: 184 },
    { field: 'description', width: 384 },
  ];

  visibleData: any[] = [];
  rowHeights: number[] = [];

  onRange(e: PretextScrollEvent) {
    this.visibleData = this.data.slice(e.start, e.end);
    this.rowHeights = e.rowHeights;
  }
}

API

PretextVirtualScrollDirective

Input Type Default Description
data any[] required Full data array
columns PretextColumnDef[] required Column field + text width
font string '14px system-ui' CSS font shorthand
lineHeight number 20 Line height in px
rowPadding number 16 Vertical padding per row
minRowHeight number 32 Minimum row height
rowGap number 0 Gap between rows
scrollHeight string '400px' Viewport height
bufferRows number 5 Buffer rows above/below
Output Type Description
visibleRangeChange PretextScrollEvent Emits when visible range changes
Method Description
scrollToIndex(index, behavior?) Scroll to a specific row

PretextRowHeightService

Low-level service for direct control:

const cache = service.prepareRows(data, columns, font);
const heights = service.calculateRowHeights(cache, columns, lineHeight, padding);
const positions = service.buildPositionIndex(heights);
const range = service.findVisibleRange(positions, scrollTop, viewportHeight);

How it works

  1. Prepare (once) — @chenglou/pretext segments text and measures via canvas
  2. Layout (on resize) — pure arithmetic, ~0.0002ms per cell, no DOM access
  3. Scroll (continuous) — O(log n) binary search in cumulative position arrays

License

MIT