Column Pinning

Column pinning keeps columns visible at the left or right edge of the table while scrolling horizontally. Enable "Split pinned columns into multiple tables" to render pinned columns as separate table elements, which is useful when you need independent scrolling regions.

Username
Role
Account Status
Last Visited At
Visit Count
Kathryne_Greenfelder28 moderator pending 25 Sep 2025 00:26:45 PDT 26
Constance.Larkin55 user suspended 19 Dec 2024 03:01:43 PDT 173
Mohammed_Witting13 user active 14 Sep 2025 13:32:36 PDT 34
Serenity_Thompson44 moderator suspended 26 Oct 2025 04:32:41 PDT 336
Kallie.Deckow admin suspended 23 Apr 2025 21:48:11 PDT 20
Mya_Konopelski98 moderator pending 11 Aug 2025 23:48:59 PDT 5
Kirstin.Littel12 user suspended 21 Sep 2025 03:13:33 PDT 2
Karine_Kohler user pending 21 Sep 2024 21:18:38 PDT 2
Herbert.Swift admin pending 10 Jul 2025 11:47:59 PDT 283
Owen_Bernier moderator active 19 Aug 2025 02:18:40 PDT 63
import {Component, signal} from "@angular/core"
import {FormsModule} from "@angular/forms"

import {ButtonModule} from "@qualcomm-ui/angular/button"
import {CheckboxModule} from "@qualcomm-ui/angular/checkbox"
import {ProgressRingModule} from "@qualcomm-ui/angular/progress-ring"
import {
  type AngularTable,
  createAngularTable,
  TableModule,
} from "@qualcomm-ui/angular/table"
import {getCoreRowModel} from "@qualcomm-ui/core/table"

import {columns, createUserQuery, type User} from "./data"
import {LeftTable} from "./left-table"
import {PinnableHeader} from "./pinnable-header"
import {RightTable} from "./right-table"

@Component({
  imports: [
    TableModule,
    ButtonModule,
    ProgressRingModule,
    FormsModule,
    CheckboxModule,
    PinnableHeader,
    LeftTable,
    RightTable,
  ],
  selector: "column-pinning-demo",
  template: `
    <div class="flex w-full flex-col gap-4 p-2">
      <div class="flex flex-wrap items-center gap-2">
        <button q-button variant="outline" (click)="query.refetch()">
          Regenerate
        </button>
        @if (query.isFetching()) {
          <div q-progress-ring size="xs"></div>
        }
      </div>

      <div>
        <label
          label="Split pinned columns into multiple tables"
          q-checkbox
          size="sm"
          [(ngModel)]="isSplit"
        ></label>
      </div>

      <div class="flex gap-4">
        @if (isSplit() && table().getIsSomeColumnsPinned("left")) {
          <left-table [table]="table" />
        }

        @if (
          (isSplit() && table().getCenterFlatHeaders().length) || !isSplit()
        ) {
          <div q-table-root>
            <div q-table-scroll-container>
              <table q-table-table>
                <thead q-table-header>
                  @for (
                    headerGroup of isSplit()
                      ? table.getCenterHeaderGroups()
                      : table.getHeaderGroups();
                    track headerGroup.id
                  ) {
                    <tr q-table-row>
                      @for (header of headerGroup.headers; track header.id) {
                        <th
                          pinnable-header
                          q-table-header-cell
                          [header]="header"
                        ></th>
                      }
                    </tr>
                  }
                </thead>
                <tbody q-table-body>
                  @for (row of table.getRowModel().rows; track row.id) {
                    <tr q-table-row>
                      @for (
                        cell of isSplit()
                          ? row.getCenterVisibleCells()
                          : row.getVisibleCells();
                        track cell.id
                      ) {
                        <td q-table-cell>
                          <ng-container *renderCell="cell; let value">
                            {{ value }}
                          </ng-container>
                        </td>
                      }
                    </tr>
                  }
                </tbody>
              </table>
            </div>
          </div>
        }

        @if (isSplit() && table().getIsSomeColumnsPinned("right")) {
          <right-table [table]="table" />
        }
      </div>
    </div>
  `,
})
export class ColumnPinningDemo {
  protected readonly query = createUserQuery(10)

  protected readonly isSplit = signal(false)

  protected table: AngularTable<User> = createAngularTable(() => ({
    columns,
    data: this.query.data() || [],
    getCoreRowModel: getCoreRowModel(),
  }))
}
Last updated on by Ryan Bower