Framework:Javascript Data GridAngular Data GridReact Data GridVue Data Grid

React Data Grid: Row Dragging

Row dragging is used to rearrange rows by dragging the row with the mouse. To enable row dragging, set the column property rowDrag on one (typically the first) column.

Enabling Row Dragging

rowDrag
boolean | RowDragCallback
boolean or Function. Set to true (or return true from function) to allow row dragging.
Default: false
rowDrag: boolean | RowDragCallback<TData>;

interface RowDragCallback<TData = any> {
    (params: RowDragCallbackParams<TData>) : boolean
}

interface RowDragCallbackParams<TData = any> {
  // Row node for the given row 
  node: RowNode<TData>;
  // Data associated with the node. Will be `undefined` for group rows. 
  data: TData | undefined;
  // Column for this callback 
  column: Column;
  // ColDef provided for this column 
  colDef: ColDef<TData>;
  // The grid api. 
  api: GridApi<TData>;
  // The column api. 
  columnApi: ColumnApi;
  // Application context as set on `gridOptions.context`. 
  context: any;
}

To enable row dragging on all columns, set the column property rowDrag = true on one (typically the first) column.

const columnDefs = [
    // make all rows draggable
    { field: 'athlete', rowDrag: true },
];

<AgGridReact columnDefs={columnDefs}></AgGridReact>

It is also possible to dynamically control which rows are draggable by providing a callback function as shown below:

const columnDefs = [
    // only allow non-group rows to be dragged
    { field: 'athlete', rowDrag: params => !params.node.group },
];

<AgGridReact columnDefs={columnDefs}></AgGridReact>

There are two ways in which row dragging works in the grid, managed and unmanaged:

Managed Dragging

In managed dragging, the grid is responsible for rearranging the rows as the rows are dragged. Managed dragging is enabled with the property rowDragManaged=true.

The example below shows simple managed dragging. The following can be noted:

The logic for managed dragging is simple and has the following constraints:

These constraints can be bypassed by using unmanaged row dragging.

Suppress Move When Dragging

By default, the managed row dragging moves the rows while you are dragging them. This effect might not be desirable due to your application design. To prevent this default behaviour, set suppressMoveWhenRowDragging to true in the gridOptions.

Multi-Row Dragging

It is possible to drag multiple rows at the same time, when rowDragMultiRow is set to true in the gridOptions and it is combined with rowSelection='multiple'.

For this example note the following:

Unmanaged Dragging

Unmanaged dragging is the default dragging for the grid. To use it, do not set the property rowDragManaged. Unmanaged dragging differs from managed dragging in the following ways:

It is not possible for the grid to provide a generic solution for row dragging that fits all usage scenarios. The way around this is the grid fires events and the application is responsible for implementing what meets the application's requirements.

Row Drag Events

There are four grid events associated with row dragging which are:

Typically a drag will fire the following events:

  1. rowDragEnter fired once - The drag has started.
  2. rowDragMove fired multiple times - The mouse is dragging over the rows.
  3. rowDragEnd fired once - The drag has finished.

Additional rowDragLeave and rowDragEnter events are fired if the mouse leaves or re-enters the grid. If the drag is finished outside of the grid, then the rowDragLeave is the last event fired and no rowDragEnd is fired, as the drag did not end on the grid.

Each of the four row drag events extend the RowDragEvent interface.

Properties available on the RowDragEvent<TData = any> interface.

type
string
Event identifier: One of rowDragEnter, rowDragMove, rowDragEnd, rowDragLeave
node
RowNode
The row node getting dragged. Also the node that started the drag when multi-row dragging.
nodes
RowNode[]
The list of nodes being dragged.
event
MouseEvent
The underlying mouse move event associated with the drag.
vDirection
string
Direction of the drag, either 'up', 'down' or null (if mouse is moving horizontally and not vertically).
overIndex
number
The row index the mouse is dragging over or -1 if over no row.
overNode
RowNode
The row node the mouse is dragging over or undefined if over no row.
y
number
The vertical pixel location the mouse is over, with 0 meaning the top of the first row. This can be compared to the rowNode.rowHeight and rowNode.rowTop to work out the mouse position relative to rows. The provided attributes overIndex and overNode means the y property is mostly redundant. The y property can be handy if you want more information such as 'how close is the mouse to the top or bottom of the row?'
api
GridApi
GridApi
columnApi
ColumnApi
ColumnApi

Example Events

The below example demonstrates unmanaged row dragging with no attempt by the application or the grid to re-order the rows - this is on purpose to demonstrate the grid will not attempt to re-order rows unless you set the rowDragManaged property. The example also demonstrates all the events that are fired.

From the example the following can be noted:

// Loading...

Simple Unmanaged Example

The example below shows how to implement simple row dragging using unmanaged row dragging and events. The example behaves the same as the Managed Dragging example above, however the logic for moving the rows is in the application rather than the grid.

From the example the following can be noted:

// Loading...

The simple example doesn't add anything that managed dragging gives (the first example on this page). Things get interesting when we introduce complex scenarios such as row grouping or tree data, which are explained below.

Dragging Multiple Rows with unmanaged row dragging, the application is in control of what gets dragged, so it is possible to use the events to drag more than one row at a time, e.g. to move all selected rows in one go if using row selection.

Entire Row Dragging

When using row dragging it is also possible to reorder rows by clicking and dragging anywhere on the row without the need for a drag handle by enabling the rowDragEntireRow grid option as shown below:

const columnDefs = [
    { field: 'country' },
    { field: 'year' },
    { field: 'sport' },
    { field: 'total' }
];
// allows rows to dragged without the need for drag handles
const rowDragEntireRow = true;

<AgGridReact columnDefs={columnDefs} rowDragEntireRow={rowDragEntireRow}></AgGridReact>

The example below demonstrates entire row dragging with Multi-Row Dragging. Note the following:

// Loading...

Range Selection is not supported when rowDragEntireRow is enabled.

Suppress Row Drag

You can hide the draggable area by calling the grid API setSuppressRowDrag() or by setting the bound property suppressRowDrag.

The example below is almost identical to the Managed Dragging example with the following differences:

// Loading...

Dragging & Row Grouping

Row Grouping in the grid allows grouping rows by a particular column. Dragging rows while grouping is possible when doing unmanaged row dragging. The application is responsible for updating the data based on the drag events fired by the grid.

The example below uses row dragging to place rows into groups. It does not try to order the rows within the group. For this reason, the logic works regardless of sorting or filtering.

The example below shows row dragging with Row Grouping where the following can be noted:

// Loading...

Row Dragging & Tree Data

Tree Data in the grid allows providing data to the grid in parent / child relationships, similar to that required for a file browser. Dragging rows with tree data is possible when doing unmanaged row dragging. The application is responsible for updating the data based on the drag events fired by the grid.

Example Tree Data

The example below shows Tree Data and row dragging where the following can be noted:

// Loading...

Example Highlighted Tree Data

The example above works, however it is not intuitive as the user is given no visual hint what folder will be the destination folder. The example below continues with the example above by providing hints to the user while the drag is in progress. From the example the following can be observed:

// Loading...

Other Row Models

Unmanaged row dragging will work with any of the row models Infinite, Server-Side and Viewport. With unmanaged dragging, the implementation of what happens when a particular drag happens is up to your application.

Because the grid implementation with regard to row dragging is identical to the above, examples of row dragging with the other row models are not given. How your application behaves with regards to the row drag events is the difficult bit, but that part is specific to your application and how your application stores its state. Giving an example here with a different data store would be redundant.

Customisation

There are some options that can be used to customise the Row Drag experience, so it has a better integration with your application.

Custom Row Drag Text

When a row drag starts, a "floating" DOM element is created to indicate which row is being dragged. By default, this DOM element will contain the same value as the cell that started the row drag. It's possible to override that text by using the colDef.rowDragText callback.

rowDragText
Function
A callback that should return a string to be displayed by the rowDragComp while dragging a row. If this callback is not set, the current cell value will be used.
rowDragText = (
    params: IRowDragItem,
    dragItemCount: number
) => string;

interface IRowDragItem {
  // The default text that would be applied to this Drag Element 
  defaultTextValue: string;
  // When dragging a row, this contains the row node being dragged
  // When dragging multiple rows, this contains the row that started the drag. 
  rowNode?: RowNode;
  // When dragging multiple rows, this contains all rows being dragged 
  rowNodes?: RowNode[];
  // When dragging columns, this contains the columns being dragged 
  columns?: Column[];
  // When dragging columns, this contains the visible state of the columns 
  visibleState?: { [key: string]: boolean; };
}
const columnDefs = [
    {
        field: 'athlete',
        rowDrag: true,
        rowDragText: (params, dragItemCount) => {
            return (
                dragItemCount > 1
                    ? (dragItemCount + ' items')
                    : params.defaultTextValue + ' is'
            ) + ' being dragged...';
        }
    }
];

<AgGridReact columnDefs={columnDefs}></AgGridReact>

The example below shows dragging with custom text. The following can be noted:

// Loading...

Row Dragger inside Custom Cell Renderers

Due to the complexity of some applications, it could be handy to render the Row Drag Component inside of a Custom Cell Renderer. This can be achieved, by using the registerRowDragger method in the ICellRendererParams as follows:

// your custom cell renderer code

// this will hold the reference to the element you want to
// to act as row dragger.
myRef = React.createRef();

componentDidMount() {
    this.props.registerRowDragger(this.myRef.current);
}

When using registerRowDragger you should not set the property rowDrag=true in the Column Definition. Doing that will cause the cell to have two row draggers.

The example below shows a custom cell renderer, with using the registerRowDragger callback to render the Row Dragger inside itself.

// Loading...

Full Width Row Dragging

It is possible to drag Full Width Rows by registering a Custom Row Dragger.

Note the following:

// Loading...

Row Dragger with Custom Start Drag Pixels

By default, the drag event only starts after the Row Drag Element has been dragged by 4px, but sometimes it might be useful to start the drag with a different drag threshold, for example, start dragging as soon as the mousedown event happens (dragged by 0px). For that reason, the registerRowDragger takes a second parameter to specify the number of pixels that will start the drag event.

Note the following:

// Loading...