# Row reordering

> Let users drag rows into their own order with a handle, for task lists, watchlists and priorities.

Row reordering adds a drag handle to the first column, so users can put rows in their own order: a task list, a watchlist, a priority queue. The grid reports where a row was dropped, and your app moves it in its own array.

Grab the ⠿ handle at the start of a row and drop it on another row:

Example: Drag to reorder tasks (row-reordering.svelte)

```svelte
<script lang="ts">
  import { Grid, type ColumnDef } from 'bo-grid';

  let tasks = $state([
    { id: 1, title: 'Wire up the login flow', owner: 'Ava', priority: 'High' },
    { id: 2, title: 'Design the empty states', owner: 'Mia', priority: 'Medium' },
    { id: 3, title: 'Fix the pager off-by-one', owner: 'Noah', priority: 'High' },
    { id: 4, title: 'Write the API docs', owner: 'Zoe', priority: 'Low' },
    { id: 5, title: 'Profile the slow query', owner: 'Ravi', priority: 'High' },
    { id: 6, title: 'Ship the release notes', owner: 'Lena', priority: 'Low' },
  ]);

  // Sorting would fight the hand-made order, so the columns don't sort.
  const columns: ColumnDef[] = [
    { type: 'text', key: 'title', header: 'Task', flex: 1, sortable: false },
    { type: 'text', key: 'owner', header: 'Owner', width: 110, sortable: false },
    { type: 'text', key: 'priority', header: 'Priority', width: 100, sortable: false },
  ];

  // The grid reports where a row moved; the app moves it in its own array.
  function reorder(from: number, to: number): void {
    const next = [...tasks];
    const [moved] = next.splice(from, 1);
    next.splice(to, 0, moved);
    tasks = next;
  }
</script>

<Grid rows={tasks} {columns} onRowReorder={reorder} height={250} />
```

## Turning it on

Pass `onRowReorder`. It receives the row's old and new positions in the rows on screen; move the row in your array and assign a new array:

```svelte
<script lang="ts">
  let tasks: GridRow[] = $state([
    { id: 1, title: 'Write the brief' },
    { id: 2, title: 'Review the pull request' },
  ]);

  function reorder(from: number, to: number): void {
    const next = [...tasks];
    const [moved] = next.splice(from, 1);
    next.splice(to, 0, moved);
    tasks = next;
  }
</script>

<Grid rows={tasks} {columns} onRowReorder={reorder} height={480} />
```

## When it applies

The positions are indices into the rows on screen, so they match your array only when the view shows it as it is:

- **Unsorted and unfiltered.** Make the columns `sortable: false`, as in the example, and don't filter a reorderable list. A sorted view would put the dropped row back in sort order anyway.
- **Flat, in memory, one page.** The handle does not appear with grouping (`groupBy`), tree data, a server data source, or paging (`pageSize`).

## In the gallery

Live example: https://bonguynvan.github.io/bo-grid/examples/tasks/ (source: https://github.com/bonguynvan/bo-grid/blob/main/src/demo/examples/)

## Reference

- `onRowReorder`: `(fromIndex: number, toIndex: number) => void` — Enable drag-to-reorder rows via a handle in the first column. Called with the from/to indices on drop — reorder your own `rows` in here. The indices are positions in the rows as shown, so they match `rows` while the list is neither sorted nor filtered. Off for grouped, paged, tree and `source` grids.

  ```svelte
  <Grid {rows} {columns} height={480}
    onRowReorder={(from, to) => { const next = [...rows]; next.splice(to, 0, ...next.splice(from, 1)); rows = next; }} />
  ```


- `sortable`: `boolean` (default `true`) — Set false to disable header-click sorting on this column.

---
Page: https://bonguynvan.github.io/bo-grid/docs/row-reordering/ · All pages: https://bonguynvan.github.io/bo-grid/llms.txt
