# Drag and Drop (Advanced)
URL: https://pro.rv-grid.com/guides/rows/row-advanced-drag-drop/
Source: src/content/docs/guides/rows/row-advanced-drag-drop.mdx
Description: Custom drag-and-drop behavior and interactions.
Implement sophisticated drag-and-drop functionality within your grid

Reorder plugin in RevoGrid may appear simple at first glance, but it’s quite a complex and powerful feature.
It supports **multi-item reordering**, allowing users to move multiple rows or columns at once while preserving the integrity of the dataset.
Leveraging **`proxyItems`** for efficient handling of the full dataset, the plugin ensures that **filter positioning remains correct** even after reordering, maintaining a seamless user experience.

Beyond its core functionality, plugin plays a **crucial role in supporting other plugins** within RevoGrid.
It facilitates **data transfer** across different operations and plugins, extending the overall capabilities of the grid.

This makes it an essential component for managing dynamic datasets in RevoGrid Pro.

- **Custom Drag-and-Drop Behavior**:
  Tailor the drag-and-drop interactions to fit your application’s specific needs. You can configure how rows are moved, allowing for both simple and complex drag-and-drop operations.

- **Enhanced Interactivity**:
  Improve the overall usability of your grid. With responsive drag-and-drop functionality, users can quickly reorganize data, making it easier to manage and visualize information.

- **Multi-Row Dragging**:
  Users can drag and drop multiple rows at once, simplifying bulk operations. This is particularly useful for scenarios where users need to rearrange large datasets quickly.

- **Flexible Dimensions**:
  Allow dragging in any direction—vertically or horizontally—supporting both pinned and classic rows. This flexibility enables users to interact with the grid in a way that feels natural to them.

- **Custom Classes During Dragging**:
  Apply custom styles during drag operations to provide visual feedback. This feature helps users understand what they are dragging and where they can drop it, enhancing the overall experience.

- **Drag Handle Customization**:
  Implement your own drag handles and apply them to custom cells without limitations. This means you can design specific elements within your rows to serve as drag handles, making it clear to users which parts of the UI are draggable.

- **Extendable Event Source**:
  Enhance functionality by extending the drag event source. You can create custom events and interactions that suit your application’s specific requirements, allowing for a more tailored user experience.

### How to use

To enable drag and drop functionality for specific columns, first, import the `RowOrderPlugin` from `@revolist/revogrid-pro` and then simply add the `rowDrag` property to the column configuration:
```ts
import { RowOrderPlugin } from '@revolist/revogrid-pro';
grid.columns = [
  { name: '🆔 ID', prop: 'id', rowDrag: true },
];

// or in row headers
grid.rowHeaders = { rowDrag: true };

// don't forget to add the plugin
grid.plugins = [RowOrderPlugin];
```

### Row Order Preview

Use `grid.rowOrder` to customize what appears in the drag preview. `prop` keeps the existing compact label behavior, and `previewProp` can be a column prop or callback when the preview label needs application-specific text:

```ts
grid.rowOrder = {
  prop: 'name',
  preview: 'compact',
  previewProp: ({ firstItem, itemCount }) => {
    const label = firstItem?.name ?? 'Rows';
    return itemCount > 1 ? `${label} and ${itemCount - 1} more` : label;
  },
};
```

`additionalData.rowOrder` is still supported for compatibility, but direct `grid.rowOrder` configuration is preferred.

### Flash Moved Rows

If `CellFlashPlugin` is installed with `RowOrderPlugin`, successfully moved rows flash automatically after the reorder is committed. The flash applies only to the dragged row or dragged selection block at its new visible position:

```ts
import { CellFlashPlugin, RowOrderPlugin } from '@revolist/revogrid-pro';

grid.plugins = [RowOrderPlugin, CellFlashPlugin];
grid.cellFlash = {
  rowDuration: 1200,
};
```

Invalid, canceled, or no-op drops do not flash. Existing `cellFlash` options control the row flash duration, CSS class, reduced-motion behavior, and whether flashing is enabled.

To keep `CellFlashPlugin` active for edits or manual flash calls but disable row-order drop flashes, set `rowOrder.flashOnDrop` to `false`:

```ts
grid.rowOrder = {
  prop: 'name',
  flashOnDrop: false,
};
```

### Live Drop Validation

Use `validateDrop` when some positions should be blocked while the user is dragging. Invalid targets are highlighted immediately and are not committed on mouseup:

```ts
grid.rowOrder = {
  prop: 'name',
  validateDrop: ({ targetIndex }) => {
    if (targetIndex === 0) {
      return {
        valid: false,
        reason: 'The first row is locked.',
      };
    }
    return { valid: true };
  },
};
```

You can also validate with events when a plugin or application controller owns the rule:

```ts
grid.addEventListener('beforerowdropvalidate', (event) => {
  if (event.detail.targetIndex === 0) {
    event.detail.result = {
      valid: false,
      reason: 'The first row is locked.',
    };
  }
});

grid.addEventListener('rowdropstatechange', (event) => {
  if (!event.detail.result.valid) {
    console.info(event.detail.result.reason);
  };
});
```

### Grouped Row Drops

When row grouping is active, row order keeps data rows inside their current group by default. This also applies when rows are selected through `RowSelectPlugin`: synthetic group rows are ignored, and only real data rows are validated. For multi-level grouping, the full configured `grouping.props` path must match before the drop is committed.

If your workflow should let users move rows between groups, enable `applyTargetGroupOnDrop`. The row-order plugin will apply the target group values to every moved row and emit normal `beforeedit` and `afteredit` events for each changed group field. Calling `event.preventDefault()` in `beforeedit` cancels the drop.

```ts
grid.grouping = {
  props: ['team', 'status'],
  expandedAll: true,
};

grid.rowOrder = {
  prop: 'name',
  preview: 'compact',
  applyTargetGroupOnDrop: true,
};

grid.addEventListener('beforeedit', (event) => {
  if (event.detail.prop === 'team' && event.detail.val === 'Archived') {
    event.preventDefault();
  }
});
```

### User-Centric Benefits

By leveraging the advanced drag-and-drop capabilities, users will experience:

- **Increased Efficiency**: Streamline workflows by allowing users to quickly rearrange rows, making data management less cumbersome.
- **Improved Data Visualization**: Users can reorganize data in a way that makes the most sense to them, leading to better insights and understanding.
- **Intuitive Interface**: A well-implemented drag-and-drop feature provides an intuitive interface, reducing the learning curve for new users.
- **Customization Flexibility**: Allowing for custom drag handles and styles gives users the ability to tailor their experience according to their preferences.

Advanced drag-and-drop functionality empowers users to interact with their data in a more dynamic and intuitive way. By customizing the behavior and appearance of drag-and-drop actions, you can significantly enhance the user experience within your grid application. Embrace these capabilities to create a more engaging and efficient interface that meets your users' needs.
