Row Ordering (Drag & Drop)

This example features row drag and drop functionality using the @angular/cdk drag and drop directives.

Username Role Account Status Account Created On Last Visited At Visit Count
Chelsie_Kohler admin suspended 29 Apr 2025 06:08:26 PDT 15 Jul 2025 11:10:46 PDT 10
Lewis_Cummings moderator active 18 Oct 2024 09:48:52 PDT 21 Jul 2025 09:13:33 PDT 75
Cyril.Gutkowski moderator active 19 Oct 2024 17:33:13 PDT 23 Nov 2024 00:52:27 PDT 2
Virginia.Bayer2 moderator suspended 05 Jan 2025 00:33:43 PDT 12 Aug 2025 10:14:00 PDT 357
Kim.Mante34 user pending 07 Feb 2025 06:56:38 PDT 16 Jul 2025 00:33:16 PDT 71
Rhiannon_Auer user pending 10 May 2025 08:59:18 PDT 05 Aug 2025 01:29:01 PDT 311
Anna_Schiller22 moderator pending 04 Nov 2024 21:38:31 PDT 29 Mar 2025 07:28:50 PDT 7
Judd_Carroll3 user pending 16 Sep 2025 06:36:31 PDT 21 Sep 2025 03:51:58 PDT 2
Jane.Haag49 admin suspended 16 Apr 2024 16:53:43 PDT 27 Apr 2025 03:21:25 PDT 243
Fidel_Ledner moderator active 21 Sep 2024 19:11:35 PDT 29 Jul 2025 06:45:46 PDT 276
import {
  CdkDrag,
  type CdkDragDrop,
  CdkDragHandle,
  CdkDropList,
  moveItemInArray,
} from "@angular/cdk/drag-drop"
import {Component, effect, signal} from "@angular/core"

import {ButtonModule} from "@qualcomm-ui/angular/button"
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 {createUserQuery, type User, userColumns} from "./data"

@Component({
  imports: [
    TableModule,
    ButtonModule,
    ProgressRingModule,
    CdkDropList,
    CdkDrag,
    CdkDragHandle,
  ],
  selector: "row-dnd-demo",
  template: `
    <div q-table-root>
      <div q-table-action-bar>
        <button
          q-button
          size="sm"
          variant="outline"
          [disabled]="query.isFetching()"
          (click)="query.refetch()"
        >
          Regenerate
        </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>
                <th q-table-header-cell></th>
                @for (header of headerGroup.headers; track header.id) {
                  <th
                    q-table-header-cell
                    [attr.colspan]="header.colSpan"
                    [style.width.px]="header.getSize()"
                  >
                    <ng-container *renderHeader="header; let value">
                      {{ value }}
                    </ng-container>
                  </th>
                }
              </tr>
            }
          </thead>
          <tbody
            cdkDropList
            q-table-body
            (cdkDropListDropped)="onRowDropped($event)"
          >
            @for (row of table.getRowModel().rows; track row.id) {
              <tr cdkDrag q-table-row>
                <td class="p-2" q-table-cell>
                  <button cdkDragHandle q-table-row-drag-handle></button>
                </td>
                @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 RowDndDemo {
  protected readonly query = createUserQuery(10)
  protected readonly mutableData = signal<User[]>([])

  constructor() {
    effect(() => {
      const data = this.query.data()
      if (data) {
        this.mutableData.set([...data])
      }
    })
  }

  protected table: AngularTable<User> = createAngularTable(() => ({
    columns: userColumns,
    data: this.mutableData(),
    getCoreRowModel: getCoreRowModel(),
    getRowId: (row) => row.userId,
  }))

  onRowDropped(event: CdkDragDrop<User[]>) {
    this.mutableData.update((data) => {
      const newData = [...data]
      moveItemInArray(newData, event.previousIndex, event.currentIndex)
      return newData
    })
  }
}
Last updated on by Ryan Bower