Row Expansion (Sub rows)
Row expansion enables tables to display hierarchical data by allowing rows to expand and reveal nested sub-rows. This is useful for representing parent-child relationships, grouped data, or tree structures within a table.
The demo below shows a table with expandable rows containing nested data. Each row with children displays an expand button that toggles visibility of its sub-rows. The header includes an expand-all button that expands or collapses all rows at once. Visual indentation indicates the depth level of each row in the hierarchy.
Username | Account Status | Role | Avg Session Duration | Company Name | Last Visited At | Visit Count |
|---|---|---|---|---|---|---|
Cara.Gislason37 | pending | admin | 119 | Will - Collins | 27 Dec 2024 01:51:32 PDT | 418 |
Earline_Heidenreich | suspended | admin | 118 | Adams, Blanda and Lang | 12 Sep 2025 08:23:20 PDT | 2 |
Dina.Hammes60 | active | user | 119 | Cruickshank Inc | 26 Nov 2024 06:52:05 PDT | 4 |
Jayda_Prosacco55 | pending | user | 23 | Lindgren, Runolfsdottir and Ernser | 25 Feb 2025 20:35:32 PDT | 18 |
Antonio.McDermott46 | pending | user | 119 | Dooley - Ruecker | 07 Jun 2025 10:19:14 PDT | 117 |
Myrl_Waelchi | active | moderator | 100 | Harvey and Sons | 03 Apr 2025 01:40:14 PDT | 3 |
Elyssa.Lesch | suspended | user | 119 | Medhurst, Schulist and Gutmann | 16 Jul 2025 14:37:21 PDT | 182 |
Nils_Spinka | pending | user | 92 | Beer Inc | 26 Aug 2024 12:27:41 PDT | 3 |
Karli_Larkin | active | moderator | 119 | Abernathy - Stiedemann | 16 Aug 2025 22:48:10 PDT | 2 |
Chandler.Barrows | suspended | admin | 116 | Casper, Marvin and Lebsack | 12 Nov 2024 18:10:12 PDT | 2 |
import {Component} from "@angular/core"
import {ButtonModule} from "@qualcomm-ui/angular/button"
import {PaginationModule} from "@qualcomm-ui/angular/pagination"
import {ProgressRingModule} from "@qualcomm-ui/angular/progress-ring"
import {
createAngularTable,
createTablePagination,
TableModule,
} from "@qualcomm-ui/angular/table"
import {
getCoreRowModel,
getExpandedRowModel,
getPaginationRowModel,
} from "@qualcomm-ui/core/table"
import {createUserQuery, type User, userColumns} from "./data"
@Component({
imports: [TableModule, PaginationModule, ButtonModule, ProgressRingModule],
selector: "row-expansion-demo",
template: `
<div q-table-root>
<div q-table-action-bar>
<button
q-button
size="sm"
variant="outline"
[disabled]="query.isFetching()"
(click)="query.refetch()"
>
Refresh Data
</button>
@if (query.isFetching()) {
<div q-progress-ring size="xs"></div>
}
</div>
<div q-table-scroll-container>
<table q-table-table>
<thead q-table-header>
@for (
headerGroup of table.getHeaderGroups();
track headerGroup.id
) {
<tr q-table-row>
@for (header of headerGroup.headers; track header.id) {
<th q-table-header-cell>
<ng-container *renderHeader="header; let value">
{{ value }}
</ng-container>
</th>
}
</tr>
}
</thead>
<tbody q-table-body>
@for (row of table.getRowModel().rows; track row.id) {
<tr q-table-row>
@for (cell of row.getVisibleCells(); track cell.id) {
<td q-table-cell>
<ng-container *renderCell="cell; let value">
{{ value }}
</ng-container>
</td>
}
</tr>
}
</tbody>
</table>
</div>
<div
q-table-pagination
[count]="pagination.count()"
[page]="pagination.page()"
[pageSize]="pagination.pageSize()"
(pageChanged)="pagination.onPageChange($event)"
>
<div *paginationContext="let context" q-pagination-page-metadata>
@let meta = context.pageMetadata;
{{ meta.pageStart }}-{{ meta.pageEnd }} of {{ meta.count }} results
</div>
<div q-pagination-page-buttons></div>
</div>
</div>
`,
})
export class RowExpansionDemo {
protected readonly query = createUserQuery(100, 5, 3)
protected table = createAngularTable<User>(() => ({
columns: userColumns,
data: this.query.data() || [],
getCoreRowModel: getCoreRowModel(),
getExpandedRowModel: getExpandedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSubRows: (row: User) => row.subRows,
}))
protected pagination = createTablePagination(this.table)
}Last updated on by Ryan Bower