Компоненты PrimeNG
TreeTable
Scroll

Scroll

Vertical with Fixed Viewport

col.header rowData[col.field]

<p-treeTable [value]="filesVerticalFixedViewport" [columns]="cols" [scrollable]="true" scrollHeight="200px">
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        { { col.header } }
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
    <tr>
      <td *ngFor="let col of columns; let i = index">
        <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
        { { rowData[col.field] } }
      </td>
    </tr>
  </ng-template>
</p-treeTable>

Flexible Viewport

col.header rowData[col.field]

<p-button (click)="showDialog()" icon="pi pi-external-link" label="View"></p-button>
<p-dialog header="Flexible ScrollHeight" [(visible)]="dialogVisible" [style]="{width: '50vw'}" [baseZIndex]="10000" [maximizable]="true" [modal]="true" [resizable]="true" [contentStyle]="{height: '300px'}">
  <p-treeTable [value]="filesFlexibleViewport" [columns]="cols" [scrollable]="true" scrollHeight="flex">
    <ng-template pTemplate="header" let-columns>
      <tr>
        <th *ngFor="let col of columns">
          { { col.header } }
        </th>
      </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
      <tr>
        <td *ngFor="let col of columns; let i = index">
          <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
          { { rowData[col.field] } }
        </td>
      </tr>
    </ng-template>
  </p-treeTable>
  <ng-template pTemplate="footer">
    <p-button icon="pi pi-check" (click)="dialogVisible=false" label="Yes"></p-button>
    <p-button icon="pi pi-times" (click)="dialogVisible=false" label="No" styleClass="p-button-secondary"></p-button>
  </ng-template>
</p-dialog>

Virtual Scroll with 100000 Nodes

col.header rowData[col.field]

<p-treeTable [value]="virtualFiles" [columns]="cols" [scrollable]="true" [rows]="100" scrollHeight="200px" [virtualScroll]="true" [virtualRowHeight]="34">
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        { { col.header } }
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
    <tr style="height:34px">
      <td *ngFor="let col of columns; let i = index">
        <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
        { { rowData[col.field] } }
      </td>
    </tr>
  </ng-template>
</p-treeTable>

Horizontal

col.header rowData[col.field]

<p-treeTable [value]="filesHorizontalScroll" [columns]="cols" [scrollable]="true" [style]="{width:'600px'}">
  <ng-template pTemplate="colgroup" let-columns>
    <colgroup>
      <col *ngFor="let col of columns" style="width:350px">
    </colgroup>
  </ng-template>
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        { { col.header } }
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
    <tr>
      <td *ngFor="let col of columns; let i = index">
        <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
        { { rowData[col.field] } }
      </td>
    </tr>
  </ng-template>
</p-treeTable>

Horizontal and Vertical

col.header rowData[col.field]

<p-treeTable [value]="filesHorizontalVerticalScroll" [columns]="cols" [scrollable]="true" scrollHeight="200px" [style]="{width:'600px'}">
  <ng-template pTemplate="colgroup" let-columns>
    <colgroup>
      <col *ngFor="let col of columns" style="width:350px">
    </colgroup>
  </ng-template>
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        { { col.header } }
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
    <tr>
      <td *ngFor="let col of columns; let i = index">
        <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
        { { rowData[col.field] } }
      </td>
    </tr>
  </ng-template>
</p-treeTable>

Frozen Columns

col.header rowData[col.field] rowData.name

<p-treeTable [value]="filesFrozenColumns" [columns]="scrollableCols" [frozenColumns]="frozenCols" [scrollable]="true" scrollHeight="200px" frozenWidth="200px">
  <ng-template pTemplate="colgroup" let-columns>
    <colgroup>
      <col *ngFor="let col of columns" style="width:250px">
    </colgroup>
  </ng-template>
  <ng-template pTemplate="header" let-columns>
    <tr>
      <th *ngFor="let col of columns">
        { { col.header } }
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-rowData="rowData" let-columns="columns">
    <tr style="height: 57px">
      <td *ngFor="let col of columns; let i = index">
        { { rowData[col.field] } }
      </td>
    </tr>
  </ng-template>
  <ng-template pTemplate="frozenbody" let-rowNode let-rowData="rowData">
    <tr style="height: 57px">
      <td>
        <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
        { { rowData.name } }
      </td>
    </tr>
  </ng-template>
</p-treeTable>