Skip to content

Column Move With Groups

ColumnMoveAdvancedPlugin enables drag-and-drop for grouped column headers. It builds on RevoGrid’s core column move behavior and adds the group-aware rules needed for ColumnGrouping columns.

Use it when your grid has nested column groups and users need to reorder whole header bands without manually rebuilding the columns array.

Source code
import {
ColumnMoveAdvancedPlugin,
RowOddPlugin,
columnTypeRenderer,
} from '@revolist/revogrid-pro';
import { defineCustomElements } from '@revolist/revogrid/loader';
defineCustomElements();
const grid = document.querySelector('revo-grid');
if (grid) {
grid.colSize = 120;
grid.source = [
{
firstName: 'John',
lastName: 'Doe',
age: 30,
street: '123 Main St',
city: 'New York',
country: 'USA',
phone: '123-456-7890',
mobile: '098-765-4321',
},
{
firstName: 'Jane',
lastName: 'Smith',
age: 28,
street: '456 Oak Ave',
city: 'São Paulo',
country: 'Brazil',
phone: '234-567-8901',
mobile: '987-654-3210',
},
{
firstName: 'Bob',
lastName: 'Johnson',
age: 35,
street: '789 Pine Rd',
city: 'Madrid',
country: 'Spain',
phone: '345-678-9012',
mobile: '876-543-2109',
},
{
firstName: 'Alice',
lastName: 'Williams',
age: 32,
street: '321 Elm St',
city: 'London',
country: 'UK',
phone: '456-789-0123',
mobile: '765-432-1098',
},
];
grid.columns = [
{
name: 'Personal Information',
columnTemplate: columnTypeRenderer,
children: [
{
prop: 'firstName',
name: 'First Name',
size: 125,
},
{
prop: 'lastName',
name: 'Last Name',
},
{
prop: 'age',
name: 'Age',
},
],
},
{
name: 'Address',
columnType: 'id',
columnTemplate: columnTypeRenderer,
children: [
{
prop: 'street',
name: 'Street',
size: 155,
},
{
prop: 'city',
name: 'City',
},
{
prop: 'country',
name: 'Country',
},
],
},
{
name: 'Contact',
columnType: 'integer',
columnTemplate: columnTypeRenderer,
children: [
{
prop: 'email',
name: 'Email',
},
{
prop: 'phone',
name: 'Phone',
},
{
prop: 'mobile',
name: 'Mobile',
},
],
},
];
grid.plugins = [ColumnMoveAdvancedPlugin, RowOddPlugin];
grid.theme = 'material';
}

Import the plugin from @revolist/revogrid-pro and register it in the grid plugins array.

import { ColumnMoveAdvancedPlugin } from '@revolist/revogrid-pro';
const grid = document.createElement('revo-grid');
grid.plugins = [ColumnMoveAdvancedPlugin];
grid.columns = [
{
name: 'Personal Information',
children: [
{ prop: 'firstName', name: 'First Name' },
{ prop: 'lastName', name: 'Last Name' },
{ prop: 'age', name: 'Age' },
],
},
{
name: 'Address',
children: [
{ prop: 'street', name: 'Street' },
{ prop: 'city', name: 'City' },
{ prop: 'country', name: 'Country' },
],
},
];

ColumnMoveAdvancedPlugin extends the core ColumnMovePlugin implementation, so you do not need a separate column-move plugin entry for the common setup.

Groups use the standard RevoGrid ColumnGrouping shape: a header object with a name and a children array. Children can be regular columns or another nested group.

grid.columns = [
{
name: 'Customer',
children: [
{ prop: 'name', name: 'Name' },
{
name: 'Contact',
children: [
{ prop: 'email', name: 'Email' },
{ prop: 'phone', name: 'Phone' },
],
},
],
},
{
name: 'Location',
children: [
{ prop: 'city', name: 'City' },
{ prop: 'country', name: 'Country' },
],
},
];

Leaf columns keep their normal column behavior: data binding, templates, sorting, filtering, resizing, and editing still belong to the regular column definitions.

Dragging a group header moves all leaf columns owned by that group as one block. During the drag, the drop indicator snaps to valid group boundaries instead of arbitrary leaf-column positions.

When the move completes, the plugin remaps the internal group indexes for every group level. This is the part plain ColumnMovePlugin does not handle for grouped headers.

Dragging an individual leaf column still works, but the plugin keeps the column inside its current group at the active grouping depth. This prevents a single leaf column from being dropped into a different group and leaving the header tree inconsistent.

Group integrity

Move a group by dragging the group header. Move a single leaf column by dragging the leaf header. Leaf-column moves are constrained to the compatible group area.

The plugin uses the standard column drag event names.

EventWhen it firesCancelable
columndragstartBefore drag state is created. The detail is the dragged column or group data.Yes
beforecolumndragendBefore the order is committed. The detail includes startPosition, newPosition, and moved items.Yes
columndragendAfter a successful drag flow finishes.No
grid.addEventListener('columndragstart', (event) => {
const data = event.detail;
if ('children' in data) {
console.log('Group drag started:', data.name);
}
});
grid.addEventListener('beforecolumndragend', (event) => {
const { startPosition, newPosition } = event.detail;
if (!canMoveColumns(startPosition, newPosition)) {
event.preventDefault();
}
});

For framework wrappers, pass the plugin class through the wrapper’s plugins prop or input.

import { RevoGrid } from '@revolist/react-datagrid';
import { ColumnMoveAdvancedPlugin } from '@revolist/revogrid-pro';
export function CustomerGrid({ rows, columns }) {
return (
<RevoGrid
source={rows}
columns={columns}
plugins={[ColumnMoveAdvancedPlugin]}
/>
);
}
  • Works with the standard nested ColumnGrouping structure.
  • Supports nested group levels by remapping indexes across all group levels after a group move.
  • Preserves regular leaf-column drag behavior, constrained to compatible group boundaries.
  • Ignores row-header drag attempts.
  • Uses the same columndragstart, beforecolumndragend, and columndragend event names as core column moving.

Use Multi Row Headers when you need spreadsheet-style multi-level header spanning. Use Column Collapse when the same grouped headers should collapse or expand.