Row Reorder Plugin
The Row Reorder plugin lets users rearrange rows by dragging a grip handle or using keyboard shortcuts. Ideal for priority lists, task ordering, or any data where sequence matters.
Installation
Section titled “Installation”import '@toolbox-web/grid/features/reorder-rows';Basic Usage
Section titled “Basic Usage”Enable the feature and a drag handle column appears automatically. Users can drag rows to new positions or use Ctrl+Up/Down to move the focused row.
import { queryGrid } from '@toolbox-web/grid';
const grid = queryGrid('tbw-grid');grid.gridConfig = { columns: [ { field: 'priority', header: '#', type: 'number', width: 50 }, { field: 'task', header: 'Task' }, { field: 'status', header: 'Status' }, ], features: { reorderRows: { dragHandlePosition: 'left', enableKeyboard: true, animation: 'flip', }, },};
// Listen for row movesgrid.on('row-move', ({ fromIndex, toIndex }) => { console.log(`Moved row from ${fromIndex} to ${toIndex}`); // Optionally persist the new order to your backend});import '@toolbox-web/grid-react/features/reorder-rows';import { DataGrid } from '@toolbox-web/grid-react';
function ReorderableTaskList({ tasks }) { return ( <DataGrid rows={tasks} columns={[ { field: 'priority', header: '#', type: 'number', width: 50 }, { field: 'task', header: 'Task' }, { field: 'status', header: 'Status' }, ]} reorderRows onRowMove={(e) => console.log('Row moved:', e.detail)} /> );}<script setup>import '@toolbox-web/grid-vue/features/reorder-rows';import { TbwGrid, TbwGridColumn, useGridEvent } from '@toolbox-web/grid-vue';import { ref } from 'vue';
const gridRef = ref(null);const tasks = [ { priority: 1, task: 'Review PR', status: 'Pending' }, { priority: 2, task: 'Deploy staging', status: 'In Progress' },];
useGridEvent(gridRef, 'row-move', (e) => { console.log('Row moved:', e.detail);});</script>
<template> <TbwGrid ref="gridRef" :rows="tasks" reorder-rows> <TbwGridColumn field="priority" header="#" type="number" :width="50" /> <TbwGridColumn field="task" header="Task" /> <TbwGridColumn field="status" header="Status" /> </TbwGrid></template>// Feature import - enables the [rowReorder] inputimport '@toolbox-web/grid-angular/features/reorder-rows';
import { Component } from '@angular/core';import { Grid } from '@toolbox-web/grid-angular';import type { ColumnConfig } from '@toolbox-web/grid';
@Component({ selector: 'app-task-list', imports: [Grid], template: ` <tbw-grid [rows]="rows" [columns]="columns" [reorderRows]="true" (row-move)="onRowMove($event)" style="height: 400px; display: block;"> </tbw-grid> `,})export class TaskListComponent { rows = [ { priority: 1, task: 'Review PR', status: 'Pending' }, { priority: 2, task: 'Deploy staging', status: 'In Progress' }, ];
columns: ColumnConfig[] = [ { field: 'priority', header: '#', type: 'number', width: 50 }, { field: 'task', header: 'Task' }, { field: 'status', header: 'Status' }, ];
onRowMove(e: CustomEvent) { console.log('Row moved:', e.detail); }}Default Row Reorder
Section titled “Default Row Reorder”ROW REORDER
Handle position Position of drag handle column
Keyboard enabled Allow reorder with keyboard shortcuts
Animation Reorder animation style
<tbw-grid style="height: 350px;"></tbw-grid>import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/reorder-rows';
const sampleData = [ { id: 1, name: 'Alice', department: 'Engineering', email: 'alice@example.com', priority: 1 }, { id: 2, name: 'Bob', department: 'Marketing', email: 'bob@example.com', priority: 2 }, { id: 3, name: 'Carol', department: 'Engineering', email: 'carol@example.com', priority: 3 }, { id: 4, name: 'David', department: 'Sales', email: 'david@example.com', priority: 4 }, { id: 5, name: 'Eve', department: 'Engineering', email: 'eve@example.com', priority: 5 },];const columns = [ { field: 'priority', header: '#', type: 'number', width: 50 }, { field: 'name', header: 'Name' }, { field: 'department', header: 'Department' }, { field: 'email', header: 'Email' },];
const grid = queryGrid('tbw-grid')!;
function rebuild(dragHandlePosition = 'left', enableKeyboard = true, animation = 'flip') { grid.gridConfig = { columns, features: { reorderRows: { dragHandlePosition, enableKeyboard, animation: animation === 'false' ? false : animation } as any }, }; grid.rows = sampleData;}
rebuild();Drag the grip handle (☰) to reorder rows. Use Ctrl+Up/Down to move the focused row with the keyboard.
Cancelable Events
Section titled “Cancelable Events”Try moving "Bob" - it will be blocked!
<div style="padding: 8px; margin-bottom: 8px; background: var(--tbw-color-bg-alt); border-radius: 4px;">Try moving "Bob" - it will be blocked!</div><tbw-grid style="height: 350px;"></tbw-grid>import '@toolbox-web/grid';import { queryGrid } from '@toolbox-web/grid';import '@toolbox-web/grid/features/reorder-rows';
// Sample data for row reorder demosconst sampleData = [ { id: 1, name: 'Alice', department: 'Engineering', email: 'alice@example.com', priority: 1 }, { id: 2, name: 'Bob', department: 'Marketing', email: 'bob@example.com', priority: 2 }, { id: 3, name: 'Carol', department: 'Engineering', email: 'carol@example.com', priority: 3 }, { id: 4, name: 'David', department: 'Sales', email: 'david@example.com', priority: 4 }, { id: 5, name: 'Eve', department: 'Engineering', email: 'eve@example.com', priority: 5 },];const columns = [ { field: 'priority', header: '#', type: 'number', width: 50 }, { field: 'name', header: 'Name' }, { field: 'department', header: 'Department' }, { field: 'email', header: 'Email' },];
const status = document.getElementById('row-reorder-cancelable-status')!;
const grid = queryGrid('tbw-grid');
grid.gridConfig = { columns, features: { reorderRows: true },};grid.rows = sampleData;
// Prevent moving Bobgrid.on('row-move', (detail, e) => { if (detail.row.name === 'Bob') { e.preventDefault(); status.textContent = '❌ Cannot move Bob!'; status.style.background = 'var(--tbw-color-danger-light)'; } else { status.textContent = `✓ Moved ${detail.row.name} from index ${detail.fromIndex} to ${detail.toIndex}`; status.style.background = 'var(--tbw-color-success-light)'; }});Cancel row moves by calling event.preventDefault() in the row-move handler.
Configuration Options
Section titled “Configuration Options”See RowReorderConfig for the full list of options and defaults.
Events
Section titled “Events”| Event | Detail | Cancelable | Description |
|---|---|---|---|
row-move | RowMoveDetail | Yes | Fired when a row move is attempted. Call preventDefault() to block. |
Keyboard Shortcuts
Section titled “Keyboard Shortcuts”| Key | Action |
|---|---|
Ctrl + ↑ | Move focused row up |
Ctrl + ↓ | Move focused row down |
Styling
Section titled “Styling”The plugin adds these CSS classes you can customize:
| Class | Description |
|---|---|
.dg-row-drag-handle | The drag handle element |
.dg-row-drag-handle:hover | Handle hover state |
.data-grid-row.dragging | Row currently being dragged |
.data-grid-row.drop-target | Row being hovered as drop target |
.data-grid-row.drop-before | Drop indicator showing insertion above |
.data-grid-row.drop-after | Drop indicator showing insertion below |
Custom Handle Icon
Section titled “Custom Handle Icon”Override the default grip icon via CSS:
.dg-row-drag-handle::before { content: '⋮⋮'; /* Double vertical ellipsis */}- Row Identification: Uses
getRowId()fromGridConfigif defined, otherwise falls back to array index. - Data Mutation: The plugin reorders
grid.rowsin place. Therow-moveevent provides the updated array. - Virtualization: Works with virtualized grids - only visible rows are rendered but logical indices are preserved.
- Keyboard Debounce: Rapid keyboard moves are debounced (150ms) to prevent excessive rerenders.
See Also
Section titled “See Also”- Column Reorder — Drag-to-reorder columns
- Selection — Row and cell selection
AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt