Home/Rows/Row Drag & Drop
Rows

Row Drag & Drop

Drag any row by its handle to reorder it within the grid. Choose managed mode to let the grid apply the new order automatically, or manual mode to intercept the drop and persist the result yourself.

Drag any row using the ⠿ handle — order is preserved automatically (managed mode)
Full Name
Role
Team
Experience
Alice Smith
Frontend Engineer
Design System
5 years
Bob Johnson
Backend Engineer
Core API
3 years
Carol Williams
Product Manager
Growth
7 years
David Brown
QA Lead
Infrastructure
4 years
Emma Jones
UX Designer
Design System
6 years
Frank Miller
DevOps Architect
Infrastructure
8 years
Grace Davis
Security Analyst
Core API
5 years
Henry Wilson
Mobile Engineer
Growth
2 years
All records loaded
8 / 8 records

Enabling row drag

Set rowDrag.enabled: true in GridConfig. A drag handle column appears automatically on the left. Set rowDrag.position to move it.

readonly config: GridConfig<T> = {
  rowDrag: {
    enabled: true,
    position: 'left',   // or 'right'
    managed: true,
  },
};

Managed vs manual mode

Control what happens after a successful drop with rowDrag.managed:

  • managed: true — the grid applies the new row order instantly. (rowDragEnd) still fires so you can persist the result to an API.
  • managed: false (default) — the grid emits (rowDragEnd) and waits. Read event.rows — the full reordered array — and update your data source yourself.
// Manual mode — persist the new order yourself
async onDragEnd(e: RowDragEvent): Promise<void> {
  this.data = e.rows;               // e.rows = full array in new order
  await this.api.saveOrder(e.rows); // persist to server
}

RowDragEvent fields

  • row — the row that was dragged
  • rows — the complete array in its new order
  • fromIndex / toIndex — original and final positions (zero-based)

When drag pauses automatically

A manual row order can't survive a view whose order is computed: while a client-side sort (sortMode: 'client' with active sorts), a client-side filter (filterApplyMode: 'client' with an active query), or grouping / tree data is shaping the view, the drag handles disappear and a one-time console message explains why. Clear the sorts or the filter — or switch off grouping / tree data — and the handles come right back, nothing to configure. (A grouped or hierarchical view re-buckets rows on every render, so a dropped row couldn't hold its position anyway.)

Locking specific rows

Set rowDrag.canDrag to a predicate to prevent certain rows from being moved. Rows where it returns false show no handle.

rowDrag: {
  enabled: true,
  canDrag: (row) => !row.locked,  // lock rows with locked: true
}

Interaction with sorting

Row drag and column sorting can coexist, but applying a sort overrides any manual order. If stable manual ordering matters, disable sorting on those columns or indicate in the UI that re-sorting resets the arrangement.

Auto-scroll

Hold a dragged row near the top or bottom edge of the grid to scroll automatically. Reordering within long lists works without releasing the drag.

Mouse interactions

InteractionEffect
Drag the ⠿ handleLifts the row as a ghost; a drop indicator tracks the target position
Hold near top/bottom edgeAuto-scrolls the grid while dragging
DropReorders (managed mode) and emits (rowDragEnd) with the full new order

Applying a column sort overrides any manual row order. If a stable manual arrangement matters, disable sorting on those columns — or make it clear in the UI that sorting resets the order.

Row drag API

PropertyTypeDefaultDescription
config.rowDrag.enabledbooleanfalseAdds the drag-handle column; position picks the side.
config.rowDrag.managedbooleanfalsetrue lets the grid apply the new order instantly; false emits and waits for you to update the data.
config.rowDrag.canDrag(row) => boolean—Rows returning false show no handle and cannot be moved.
(rowDragEnd)RowDragEvent—{ row, rows, fromIndex, toIndex } — rows is the complete array in its new order; persist it here.