Background:
By default, the Wijmo FlexGrid only allows rows to be dragged using the row header, which disappears when headersVisibility is set to "Column", disabling row dragging. With a bit of custom code in React, we can restore row dragging by making every data cell draggable and handling drag/drop logic manually.
Steps to Complete:
- Mark cells in every row as draggable using the
formatItemevent. - Attach
dragstart,dragover, anddrophandlers to the grid to track the dragged row and drop location. - Reorder the underlying data array based on where the row is dropped.
- Refresh the grid’s collection view so the UI updates.
Getting Started:
Mark cells in every row as draggable using the formatItem event
This runs for every rendered cell, restricts logic to data cells only, and enables native HTML drag events on each row’s cells.
flex.formatItem.addHandler((s, e) => {
if (e.panel === s.cells) {
e.cell.setAttribute('draggable', 'true');
}
});
Attach dragstart, dragover, and drop handlers to the grid to track the dragged row and drop location
This captures which row is being dragged, enables dropping, and determines where the row is released.
const host = flex.hostElement;
let draggedRowIndex = -1;
host.addEventListener('dragstart', (e: DragEvent) => {
const ht = flex.hitTest(e);
draggedRowIndex = ht.row;
});
host.addEventListener('dragover', (e: DragEvent) => {
e.preventDefault(); // required for drop to fire
});
host.addEventListener('drop', (e: DragEvent) => {
const ht = flex.hitTest(e);
const dropRowIndex = ht.row;
reorderRows(draggedRowIndex, dropRowIndex);
e.preventDefault();
});
Reorder the underlying data array based on where the row is dropped
This removes the dragged item from its original position, inserts it at the drop index, and keeps the same object reference.
function reorderRows(from: number, to: number) {
if (from === to || from < 0 || to < 0) return;
const item = items.splice(from, 1)[0];
items.splice(to, 0, item);
flex.collectionView.refresh();
}
Refresh the grid’s collection view so the UI updates
This forces FlexGrid to re-read itemsSource and triggers a visual re-render.
flex.collectionView.refresh();
File for context
import { FlexGrid } from '@mescius/wijmo.react.grid';
import * as wjcGrid from '@mescius/wijmo.grid';
import { useRef, useEffect, useState } from 'react';
function App() {
const flexRef = useRef<wjcGrid.FlexGrid | null>(null);
const [items] = useState(getData());
useEffect(() => {
const flex = flexRef.current;
if (!flex) return;
// formatItem + drag logic goes here
}, []);
return (
<FlexGrid
initialized={grid => (flexRef.current = grid)}
itemsSource={items}
headersVisibility="Column"
/>
);
}
With this React setup, every cell in a FlexGrid row can be dragged to reorder rows even when no row header is shown. The drag/drop behavior is implemented using standard DOM events and Wijmo’s hitTest method to map mouse positions to grid rows.
Happy coding!
Andrew Peterson