Skip to content

Managed Row Dragging

Enterprise

Managed row dragging lets the user pick up a row, drag it to a new position, and drop it — and the grid does the rest: it reorders the underlying data and re-renders so the change is permanent. “Managed” is the distinction — you don’t wire up the reorder yourself (that’s Unmanaged Row Dragging), the grid manages the order for you.

It ships in @zengrid/enterprise as RowDragManager. Construct one, attach it to the grid, and rows become draggable:

import { RowDragManager } from '@zengrid/enterprise/grid';
const drag = new RowDragManager(); // whole-row dragging
const grid = new Zengrid(mount, { columns, /* … */ });
grid.setData(rows);
drag.attach(grid); // wire it onto the live grid

As you drag, a drop indicator shows exactly where the row will land. Release, and RowDragManager reorders the grid’s data through its own setData — the row stays where you dropped it.

By default the whole row is draggable — press anywhere on it and go. Pass { handle: true } to require an explicit grip instead, and add the rowDragColumn() helper to render one:

import { RowDragManager, rowDragColumn } from '@zengrid/enterprise/grid';
const drag = new RowDragManager({ handle: true });
const grid = new Zengrid(mount, {
columns: [
rowDragColumn(), // the grip column
{ field: 'name', header: 'Name' },
// …
],
});
grid.setData(rows);
drag.attach(grid);

Handle mode keeps ordinary clicks (selection, editing) on the rest of the row free and reserves dragging for the grip.

Option Default Effect
handle false false drags from anywhere on the row; true drags only from a rowDragColumn() cell.

The rowDragColumn() helper takes its own presentation options:

Option Default Effect
glyph '⠿' The grip character painted into each handle cell.
width 44 Column width in pixels.
header '' Header label for the grip column.
field '__rowdrag__' Column id (carries no data).
className Extra CSS class applied to each handle cell.

drag.onChange(fn) fires once per committed reorder with both the on-screen and the source (dataset) indices, so you can persist the new order server-side or update a model:

drag.onChange(({ fromRow, toRow, fromSource, toSource }) => {
// fromRow/toRow: on-screen positions · fromSource/toSource: dataset indices
saveOrder(fromSource, toSource);
});

It returns an unsubscribe function, and drag.detach() tears everything down. Managed dragging reorders the natural (unsorted) data order, so use it on a grid without an active sort.

Drag a row and drop it somewhere new — the grid keeps the order. Switch tabs to compare whole-row dragging, a dedicated handle, and a custom grip wired to the reorder callback.

Press any cell and drag the row up or down — the line shows where it lands. Drop to commit; the grid keeps the new order.