---
title: "Managed Row Dragging"
framework: react
version: "36.1.0"
---

# Managed Row Dragging

In managed row 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 first column has `rowDrag=true` which results in a draggable area being included in the cell.
- The property `rowDragManaged` is set, to tell the grid to move the row as the row is dragged.
- If a sort (click on the header) or filter (open up the column menu) is applied to the column, the draggable icon for row dragging is disabled. This is consistent with the constraints explained after the example.

#### Row Drag Simple Managed

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  RowDragModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  NumberFilterModule,
  RowDragModule,
  ClientSideRowModelModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", rowDrag: true },
    { field: "country" },
    { field: "year", width: 100 },
    { field: "date" },
    { field: "sport" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      width: 170,
      filter: true,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            rowDragManaged={true}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Row Drag Simple Managed](https://www.ag-grid.com/examples/row-dragging-managed/simple-managed/reactFunctionalTs/)

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

- Works with [Client-Side](https://www.ag-grid.com/react-data-grid/row-models/#client-side) row model only; not with the [Infinite](https://www.ag-grid.com/react-data-grid/infinite-scrolling/), [Server-Side](https://www.ag-grid.com/react-data-grid/server-side-model/) or [Viewport](https://www.ag-grid.com/react-data-grid/viewport/) row models.
- Does not work if [Pagination](https://www.ag-grid.com/react-data-grid/row-pagination/) is enabled.
- Does not work when sorting is applied. This is because the sort order of the rows depends on the data and moving the data would break the sort order.
- Does not work when filtering is applied. This is because a filter removes rows making it impossible to know the 'real' order of rows when some are missing.

These constraints can be bypassed by using [Unmanaged Row Dragging](https://www.ag-grid.com/react-data-grid/row-dragging-unmanaged/).

See also [Row Dragging with Row Groups](https://www.ag-grid.com/react-data-grid/grouping-row-dragging/) for Grouping, that supports both managed and unmanaged row dragging.

See also [Row Dragging with Tree Data](https://www.ag-grid.com/react-data-grid/tree-data-row-dragging/) for Tree Data, that supports both managed and unmanaged row dragging.

See also [Row Drag Events](https://www.ag-grid.com/react-data-grid/row-dragging-unmanaged/#row-drag-events).

## 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`.

#### Row Drag with SuppressMoveWhenRowDragging

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  RowDragModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  NumberFilterModule,
  RowDragModule,
  ClientSideRowModelModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", rowDrag: true },
    { field: "country" },
    { field: "year", width: 100 },
    { field: "date" },
    { field: "sport" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      width: 170,
      filter: true,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            rowDragManaged={true}
            suppressMoveWhenRowDragging={true}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Row Drag with SuppressMoveWhenRowDragging](https://www.ag-grid.com/examples/row-dragging-managed/managed-suppress-move-when-dragging/reactFunctionalTs/)

## 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.mode='multiRow'`.

For this example note the following:

- When you select multiple items and drag one of them, all items in the selection will be dragged.
- When you drag an item that is not selected while other items are selected, only the unselected item will be dragged.

#### Row Drag with Multi-Row Drag

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  RowDragModule,
  RowSelectionModule,
  RowSelectionOptions,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  NumberFilterModule,
  RowDragModule,
  RowSelectionModule,
  ClientSideRowModelModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", rowDrag: true },
    { field: "country" },
    { field: "year", width: 100 },
    { field: "date" },
    { field: "sport" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      width: 170,
      filter: true,
    };
  }, []);
  const rowSelection = useMemo<
    RowSelectionOptions | "single" | "multiple"
  >(() => {
    return { mode: "multiRow", headerCheckbox: false };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            rowDragManaged={true}
            rowDragMultiRow={true}
            rowSelection={rowSelection}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Row Drag with Multi-Row Drag](https://www.ag-grid.com/examples/row-dragging-managed/managed-with-multi-row-drag/reactFunctionalTs/)

## Suppress Row Drag

You can hide the draggable area by setting the grid option `suppressRowDrag = true`.

The example below is almost identical to the [Managed Dragging](https://www.ag-grid.com/react-data-grid/row-dragging-managed/) example with the following differences:

- The **Suppress** button will hide the drag icons.
- The **Remove Suppress** button will un-hide the drag icons.
- Applying a sort or a filter or entering pivot mode will disable the drag icons.

#### Suppress Row Drag

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  RowDragModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  NumberFilterModule,
  RowDragModule,
  ClientSideRowModelModule,
];

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IOlympicData>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", rowDrag: true },
    { field: "country" },
    { field: "year", width: 100 },
    { field: "date" },
    { field: "sport" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      width: 170,
      filter: true,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  const onBtSuppressRowDrag = useCallback(() => {
    gridRef.current!.api.setGridOption("suppressRowDrag", true);
  }, []);

  const onBtShowRowDrag = useCallback(() => {
    gridRef.current!.api.setGridOption("suppressRowDrag", false);
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div style={{ marginBottom: "1rem" }}>
            <button onClick={onBtSuppressRowDrag}>Suppress</button>
            <button onClick={onBtShowRowDrag}>Remove Suppress</button>
          </div>

          <div style={gridStyle}>
            <AgGridReact<IOlympicData>
              ref={gridRef}
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              rowDragManaged={true}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Suppress Row Drag](https://www.ag-grid.com/examples/row-dragging-managed/suppress-row-drag/reactFunctionalTs/)

### Preventing Dropping on Certain Rows

The `isRowValidDropPosition` callback allows you to control whether a row drop is allowed during managed or unmanaged row dragging, and optionally override the rows, parent or position for the drop. This is useful for restricting where rows can be dropped or customizing drop behaviour. Returning an object allows instead to filter the rows to drop, or change the parent or the position of the drop.

This affects also the icon and label shown when dragging a row for both managed and unmanaged row dragging.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `isRowValidDropPosition` | `IsRowValidDropPositionCallback` |  |  | Called by drag and drop when rows are dragged over another row to conditionally prevent dropping the dragged row on the hovered row. The user can cancel the drop by returning `false` or customize the operation by returning a `IsRowValidDropPositionResult`. Module: [`RowDragModule`](https://www.ag-grid.com/react-data-grid/modules/). |
