Table Rendering
By now you should be familiar with this library's data model. If not, head back to the Overview guide before you continue here.
Recall the basic table component from earlier. We're going to enhance that example by rendering the data from the computed model in the template.
Rendering Process
When you create or update the table, you are modifying the model's internal state. We can query the model to retrieve the computed data and pass it to our UI components.
| Username | Account Status | Country | Last Visited | Role | Avg Session Duration |
|---|---|---|---|---|---|
| john_pond1 | active | US | 02 Sep 2025 07:21:43 PDT | user | 12 |
| anne.m15 | suspended | US | 02 Oct 2025 08:52:36 PDT | user | 35 |
| joe_dirte | pending | US | 19 Mar 2025 04:55:19 PDT | admin | 0 |
import {Component} from "@angular/core"
import {createAngularTable, TableModule} from "@qualcomm-ui/angular/table"
import {getCoreRowModel} from "@qualcomm-ui/core/table"
import {type User, userColumns, users} from "./data"
@Component({
imports: [TableModule],
selector: "basic-demo",
template: `
<div q-table-root>
<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>
`,
})
export class SimpleTableDemo {
protected table = createAngularTable<User>(() => ({
columns: userColumns,
data: users,
getCoreRowModel: getCoreRowModel(),
}))
}Breakdown
Let's unpack this example.
Memoization
We're using signals in the template to retrieve the header and cell data from the model.
@for (headerGroup of table.getHeaderGroups(); track headerGroup.id) {
<tr q-table-row></tr>
}UI Elements
This library exports several directives which automatically apply QUI styles to the associated elements. They also accept properties for modifying the table's style in specific contexts.
q-table-root
First up is the q-table-root directive, which wraps the entire table structure:
<div q-table-root>
<!-- table content -->
</div>q-table-scroll-container
The q-table-scroll-container directive provides horizontal scrolling for tables that exceed their container width:
<div q-table-root>
<div q-table-scroll-container>
<!-- table content -->
</div>
</div>q-table-table
The q-table-table directive is applied to the semantic <table> element:
<div q-table-root>
<div q-table-scroll-container>
<table showColumnDivider q-table-table></table>
</div>
</div>The q-table-table directive accepts a single optional property: showColumnDivider, which enables column dividers on associated child elements.
q-table-header
The q-table-header directive wraps the table's header columns:
<table q-table-table>
<thead q-table-header></thead>
</table>q-table-row
The q-table-row directive applies styles to the table's rows. For headers, we make a call to the table model to retrieve the header groups. This renders a row for each header group.
<table q-table-table>
<thead q-table-header>
@for (headerGroup of table.getHeaderGroups(); track headerGroup.id) {
<tr q-table-row></tr>
}
</thead>
</table>q-table-header-cell
The q-table-header-cell directive applies styles to the table's header cells. We use the *renderHeader structural directive to render the column's content. We'll elaborate more on this in the Cell Customization section.
<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>
</table>With the header section wrapped up, let's continue to the body.
q-table-body
The q-table-body directive applies styles to the table's body. We'll re-use the same q-table-row directive for the body's rows.
<table q-table-table>
<tbody q-table-body>
@for (row of table.getRowModel().rows; track row.id) {
<tr q-table-row></tr>
}
</tbody>
</table>q-table-cell
The q-table-cell directive applies styles to the table's cells. Like with the header, we use the *renderCell structural directive to dynamically render the cell based on the table's column definitions.
<table q-table-table>
<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>Bring Your Own Styles
You can use the q-table-* directives to apply QUI styles to your tables, but they aren't required. This library gives you full control: the data model is decoupled from the presentational layer. You're free to provide your own styles or classes.
<table class="custom-table">
<thead>
@for (headerGroup of table.getHeaderGroups(); track headerGroup.id) {
<tr>
@for (header of headerGroup.headers; track header.id) {
<th>
<ng-container *renderHeader="header; let value">
{{ value }}
</ng-container>
</th>
}
</tr>
}
</thead>
<tbody>
@for (row of table.getRowModel().rows; track row.id) {
<tr>
@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>Cell Customization
Continue to the Cell Customization guide to learn more about how to customize your table's cells.