Drag & drop reorder
Reorder one or many rows with the drag handle, the keyboard, or reorderRows - one change, selection follows the rows, one undo step.
Row reorder from three paths: drag a row by its drag handle zone (any reorder-family marker mode:
reorder, reorder-number, reorder-checkbox, reorder-both. In the content modes the
number and checkbox glyphs stay row-select surfaces, only the drag handle zone reorders, and a press
on the drag handle never changes the selection), press Shift+Alt+PageDown
or PageUp, or call reorderRows(rows, to) or moveRowsBy(rows, delta) programmatically.
Each emits one change with one row-id-based move operation per moved row, so
undo/redo restores the previous order in a single step. Selection and the active cell remap by
row id, so the rows that were selected stay selected at their new positions, and the dragged row
keeps the selected state it had.
A drag from a checked row moves every checked row. The rows land together at the drop line.
move operations show up here.pnpm dlx shadcn@latest add @gridcn/data-grid-row-reorder-demo
What's in the demo
rowMarkers="reorder-checkbox": a drag handle and a checkbox in the marker columnenableRowReorderon the provider (on by default): the grid-wide switch for the drag gesture- A thin line marks the drop target while dragging. The row moves on release
- Move down toolbar button:
moveRowsBy(rows, 1)for the checked rows, or the active row when none is checked - the programmatic path - Undo button (the
data-grid-historyadd-on): one click restores the pre-move order - The panel prints the last change: the number of
moveoperations, the first operation'srowIdand from/to indices, and the changesource("row-operation")
Marker drag vs programmatic
| Marker drag | reorderRows(rows, to) | moveRowsBy(rows, delta) | |
|---|---|---|---|
| Input | drag handle, mouse/touch | view indices (to is the final landing position of the first row, arrayMove semantics) | view indices and an offset |
| Rows land | together, at the drop line | together, from to | each row moves by delta, gaps stay |
| Guard checks | same as programmatic | see the no-op guards below | same as reorderRows |
| Emitted operations | one move per moved row | one move per moved row | one move per moved row |
to is the final position, not an offset: moving row 0 to index 3 shifts rows 1-3 up. The
paths are equivalent - use the drag for the interactive UX, the keys for the keyboard, and the
actions for buttons or an external "sort by drag" API.
No-op guards
reorderRows returns false (and dev-warns where the cause is a misconfiguration) when:
enableRowReorderis off, or the grid isreadOnly- a sort or filter is active (the view order belongs to the sort/filter, not the data)
- a lazy grid has unloaded holes (a reorder shifts the lazy add-on's index bookkeeping)
- the drop leaves the rows where they already are
- the list is empty, or holds an index outside the grid
See Row operations - Reorder for the full reference, including the stale-position warning for position-based data (search match counts, presence highlights in view-index form).
Related
- Row operations - insert/duplicate/delete
- Action buttons - per-row buttons
- Undo & redo - the history add-on behind the Undo button
- Lazy loading - why a lazy grid blocks reorder