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

Row Expansion

<p-table [value]="productsRowExpansion" dataKey="name">
<ng-template pTemplate="header">
  <tr>
    <th style="width: 3rem"></th>
    <th pSortableColumn="name">Name
      <p-sortIcon field="name"></p-sortIcon>
    </th>
    <th>Code</th>
    <th pSortableColumn="price">Price
      <p-sortIcon field="price"></p-sortIcon>
    </th>
    <th pSortableColumn="category">Category
      <p-sortIcon field="category"></p-sortIcon>
    </th>
    <th pSortableColumn="rating">Reviews
      <p-sortIcon field="rating"></p-sortIcon>
    </th>
    <th pSortableColumn="inventoryStatus">Status
      <p-sortIcon field="inventoryStatus"></p-sortIcon>
    </th>
  </tr>
</ng-template>
<ng-template pTemplate="body" let-product let-expanded="expanded">
  <tr>
    <td>
      <button type="button" pButton pRipple [pRowToggler]="product" class="p-button-text p-button-rounded p-button-plain" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
    </td>
    <td>{ { product.name } }</td>
    <td>{ { product.code } }</td>
    <td>{ { product.price | currency: 'USD' } }</td>
    <td>{ { product.category } }</td>
    <td>
      <p-rating [ngModel]="product.rating" [readonly]="true" [cancel]="false"></p-rating>
    </td>
    <td>
      <span [class]="'product-badge status-' + product.inventoryStatus.toLowerCase()">{ { product.inventoryStatus } }</span>
    </td>
  </tr>
</ng-template>
<ng-template pTemplate="rowexpansion" let-product>
  <tr>
    <td colspan="7">
      <div class="p-p-3">
        <p-table [value]="product.orders" dataKey="id">
          <ng-template pTemplate="header">
            <tr>
              <th pSortableColumn="id">Id
                <p-sortIcon field="price"></p-sortIcon>
              </th>
              <th pSortableColumn="customer">Customer
                <p-sortIcon field="customer"></p-sortIcon>
              </th>
              <th pSortableColumn="date">Date
                <p-sortIcon field="date"></p-sortIcon>
              </th>
              <th pSortableColumn="amount">Amount
                <p-sortIcon field="amount"></p-sortIcon>
              </th>
              <th pSortableColumn="stats">Status
                <p-sortIcon field="status"></p-sortIcon>
              </th>
              <th style="width: 4rem"></th>
            </tr>
          </ng-template>
          <ng-template pTemplate="body" let-order>
            <tr>
              <td>{ { order.id } }</td>
              <td>{ { order.customer } }</td>
              <td>{ { order.id } }</td>
              <td>{ { order.amount | currency: 'USD' } }</td>
              <td>
                <span [class]="'order-badge order-' + order.status.toLowerCase()">{ { order.status } }</span>
              </td>
              <td>
                <p-button type="button" icon="pi pi-search"></p-button>
              </td>
            </tr>
          </ng-template>
          <ng-template pTemplate="emptymessage">
            <tr>
              <td colspan="6">There are no order for this product yet.</td>
            </tr>
          </ng-template>
        </p-table>
      </div>
    </td>
  </tr>
</ng-template>
</p-table>

Row Expansion with empty cells

<p-table [value]="productsRowExpansion" dataKey="name">
  <ng-template pTemplate="header">
    <tr>
      <th style="width: 3rem"></th>
      <th pSortableColumn="name">Name
        <p-sortIcon field="name"></p-sortIcon>
      </th>
      <th>Code</th>
      <th pSortableColumn="price">Price
        <p-sortIcon field="price"></p-sortIcon>
      </th>
      <th pSortableColumn="category">Category
        <p-sortIcon field="category"></p-sortIcon>
      </th>
      <th pSortableColumn="rating">Reviews
        <p-sortIcon field="rating"></p-sortIcon>
      </th>
      <th pSortableColumn="inventoryStatus">Status
        <p-sortIcon field="inventoryStatus"></p-sortIcon>
      </th>
    </tr>
  </ng-template>
  <ng-template pTemplate="body" let-product let-expanded="expanded">
    <tr>
      <td>
        <button type="button" pButton pRipple [pRowToggler]="product" class="p-button-text p-button-rounded p-button-plain" [icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
      </td>
      <td>{ { product.name } }</td>
      <td>{ { product.code } }</td>
      <td>{ { product.price | currency: 'USD' } }</td>
      <td>{ { product.category } }</td>
      <td>
        <p-rating [ngModel]="product.rating" [readonly]="true" [cancel]="false"></p-rating>
      </td>
      <td>
        <span [class]="'product-badge status-' + product.inventoryStatus.toLowerCase()">{ { product.inventoryStatus } }</span>
      </td>
    </tr>
  </ng-template>
  <ng-template pTemplate="rowexpansion" let-product>
    <tr>
      <td colspan="7">
        <p class="p-mb-0">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sapiente assumenda ut, delectus accusantium minus fugit?</p>
      </td>
    </tr>
  </ng-template>
</p-table>