Компоненты PrimeNG
Table
Row Group

Row Group

Subheader Grouping

<p-table [value]="customersSubheaderGroupingRow" sortField="representative.name" sortMode="single" [scrollable]="true" scrollHeight="400px" rowGroupMode="subheader" groupRowsBy="representative.name" responsiveLayout="scroll">
  <ng-template pTemplate="header">
    <tr>
      <th>Name</th>
      <th>Country</th>
      <th>Company</th>
      <th>Status</th>
      <th>Date</th>
    </tr>
  </ng-template>
  <ng-template pTemplate="groupheader" let-customer>
    <tr pRowGroupHeader>
      <td colspan="5">
        <span class="p-text-bold p-ml-2">{ { customer.representative.name } }</span>
      </td>
    </tr>
  </ng-template>
  <ng-template pTemplate="groupfooter" let-customer>
    <tr class="p-rowgroup-footer">
      <td style="min-width: 80%">
        <div style="text-align: right; width: 100%">Total Customers</div>
      </td>
      <td style="width: 20%">{ { calculateCustomerTotal(customer.representative.name) } }</td>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-customer let-rowIndex="rowIndex">
    <tr>
      <td>
        { { customer.name } }
      </td>
      <td>
        <span class="image-text">{ { customer.country.name } }</span>
      </td>
      <td>
        { { customer.company } }
      </td>
      <td>
        <span [class]="'customer-badge status-' + customer.status">{ { customer.status } }</span>
      </td>
      <td>
        { { customer.date } }
      </td>
    </tr>
  </ng-template>
</p-table>

Expandable Row Groups

<p-table [value]="customersRowGroup" sortField="representative.name" sortMode="single" dataKey="representative.name" rowGroupMode="subheader" groupRowsBy="representative.name" responsiveLayout="scroll">
  <ng-template pTemplate="header">
    <tr>
      <th>Name</th>
      <th>Country</th>
      <th>Company</th>
      <th>Status</th>
      <th>Date</th>
    </tr>
  </ng-template>
  <ng-template pTemplate="groupheader" let-customer let-rowIndex="rowIndex" let-expanded="expanded">
    <tr>
      <td colspan="5">
        <button type="button" pButton pRipple [pRowToggler]="customer" class="p-button-text p-button-rounded p-button-plain p-mr-2" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
        <span class="p-text-bold p-ml-2">{ { customer.representative.name } }</span>
      </td>
    </tr>
  </ng-template>
  <ng-template pTemplate="groupfooter" let-customer>
    <tr class="p-rowgroup-footer">
      <td colspan="4" style="text-align: right">Total Customers</td>
      <td>{ { calculateCustomerTotal(customer.representative.name) } }</td>
    </tr>
  </ng-template>
  <ng-template pTemplate="rowexpansion" let-customer>
    <tr>
      <td>
        { { customer.name } }
      </td>
      <td>
        <span class="image-text">{ { customer.country.name } }</span>
      </td>
      <td>
        { { customer.company } }
      </td>
      <td>
        <span [class]="'customer-badge status-' + customer.status">{ { customer.status } }</span>
      </td>
      <td>
        { { customer.date } }
      </td>
    </tr>
  </ng-template>
</p-table>

RowSpan Grouping

<p-table [value]="customersRowGroup" rowGroupMode="rowspan" groupRowsBy="representative.name" sortField="representative.name" sortMode="single" responsiveLayout="scroll">
  <ng-template pTemplate="header">
    <tr>
      <th style="width: 3rem">#</th>
      <th>Representative</th>
      <th>Name</th>
      <th>Country</th>
      <th>Company</th>
      <th>Status</th>
      <th>Date</th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-customer let-rowIndex="rowIndex" let-rowgroup="rowgroup" let-rowspan="rowspan">
    <tr>
      <td>{ { rowIndex } }</td>
      <td *ngIf="rowgroup" [attr.rowspan]="rowspan">
        <span class="p-text-bold p-ml-2">{ { customer.representative.name } }</span>
      </td>
      <td>
        { { customer.name } }
      </td>
      <td>
        <span class="image-text">{ { customer.country.name } }</span>
      </td>
      <td>
        { { customer.company } }
      </td>
      <td>
        <span [class]="'customer-badge status-' + customer.status">{ { customer.status } }</span>
      </td>
      <td>
        { { customer.date } }
      </td>
    </tr>
  </ng-template>
</p-table>