Skip to content

Grid to Grid

Enterprise

Grid-to-grid dragging lets a row leave one grid and land in another — the staple of transfer-list, kanban, and shortlist UIs. It builds on the same RowDragManager that powers in-grid reordering: each grid has its own manager, and you connect them by handing one manager the drop zone of the other.

import { RowDragManager } from '@zengrid/enterprise/grid';
const dragA = new RowDragManager();
const dragB = new RowDragManager();
dragA.attach(gridA);
dragB.attach(gridB);
// Rows dragged out of grid A can be dropped into grid B:
dragA.addRowDropZone(dragB.getRowDropZone());

getRowDropZone() returns a RowDropZone bound to its grid — but unlike a plain external zone, this one knows how to receive a row: it shows an in-grid drop line where the row will land and, on release, inserts the dragged row’s data at that position. Register it on the source grid’s manager with addRowDropZone, and the two are connected.

By default a grid-to-grid drop is a move: the row is inserted into the target grid and removed from the source. Pass { removeSource: false } to copy instead — the source keeps its row and the target gets a duplicate:

// Move (default): the row leaves grid A.
dragA.addRowDropZone(dragB.getRowDropZone());
// Copy: grid A keeps the row, grid B gets a copy.
dragA.addRowDropZone(dragB.getRowDropZone({ removeSource: false }));
Option Default Effect
removeSource true true removes the row from the source grid on drop (a move); false leaves it (a copy).
onDrop Called after the row is inserted into the receiving grid.

Wiring is directional. dragA.addRowDropZone(dragB.getRowDropZone()) only enables A → B. For a two-way transfer, wire the mirror as well:

dragA.addRowDropZone(dragB.getRowDropZone()); // A → B
dragB.addRowDropZone(dragA.getRowDropZone()); // B → A

Because each grid keeps its own RowDragManager, dragging a row within a grid still reorders that grid — grid-to-grid transfer and in-grid reordering coexist on the same managers.

Pass onDrop to react when a row arrives — persist the change, POST to a server, or update a model. It receives the inserted rowData, the display index it landed before (insertBeforeRow), and its new source index (toSource):

dragA.addRowDropZone(
dragB.getRowDropZone({
onDrop: ({ rowData, insertBeforeRow, toSource }) => {
console.log('received', rowData, 'at', insertBeforeRow, '→ source', toSource);
},
})
);

The rows are dragged whole here (press anywhere on a row and drag). Add a drag handle or customise the drag preview exactly as you would for in-grid dragging — the same options apply.

Both grids share the same columns, so a row moves across intact. Drag a row from one grid to the other; a line shows where it will land. Switch tabs to compare a two-way move, a copy-only palette, and a one-way flow with a drop callback.

Drag a row from either grid onto the other — it moves across and the line shows where it lands. Drag within a grid to reorder it. A ghost follows the pointer across the gap.