Want to skip to the implementation? Check out these Svelte examples:
Use getters for reactive inputs such as data when passing Svelte state to createTable.
import { createTable, tableFeatures, columnOrderingFeature } from '@tanstack/svelte-table'
const features = tableFeatures({ columnOrderingFeature })
const table = createTable({
features,
columns,
get data() {
return data
},
})import { createTable, tableFeatures, columnOrderingFeature } from '@tanstack/svelte-table'
const features = tableFeatures({ columnOrderingFeature })
const table = createTable({
features,
columns,
get data() {
return data
},
})By default, columns are ordered in the order they are defined in the columns array. However, you can manually specify the column order using the columnOrder state. Other features like column pinning and grouping can also affect the column order.
There are 3 table features that can reorder columns, which happen in the following order:
Note: columnOrder state will only affect unpinned columns if used in conjunction with column pinning.
If you don't provide a columnOrder state, TanStack Table will just use the order of the columns in the columns array. However, you can provide an array of string column ids to the columnOrder state to specify the order of the columns.
If all you need to do is specify the initial column order, you can just specify the columnOrder state in the initialState table option.
const features = tableFeatures({ columnOrderingFeature })
const table = createTable({
features,
//...
initialState: {
columnOrder: ['columnId1', 'columnId2', 'columnId3'],
},
//...
})const features = tableFeatures({ columnOrderingFeature })
const table = createTable({
features,
//...
initialState: {
columnOrder: ['columnId1', 'columnId2', 'columnId3'],
},
//...
})Note: If you are using the state table option to also specify the columnOrder state, the initialState will have no effect. Only specify particular states in either initialState or state, not both.
If you need to dynamically change the column order, or set the column order after the table has been initialized, you can manage the columnOrder state just like any other table state.
In v9, the recommended way to own a state slice is with an external atom passed to the table's atoms option. External atoms give you fine-grained subscriptions anywhere in your app, and other code can read or write the column order without coupling that code to the table instance.
import { createAtom, useSelector } from '@tanstack/svelte-store'
import { createTable, tableFeatures, columnOrderingFeature } from '@tanstack/svelte-table'
import type { ColumnOrderState } from '@tanstack/svelte-table'
const features = tableFeatures({ columnOrderingFeature })
const columnOrderAtom = createAtom<ColumnOrderState>([
'columnId1',
'columnId2',
'columnId3',
])
const columnOrder = useSelector(columnOrderAtom) // subscribe wherever it is needed
const table = createTable({
features,
//...
atoms: {
columnOrder: columnOrderAtom,
},
//...
})import { createAtom, useSelector } from '@tanstack/svelte-store'
import { createTable, tableFeatures, columnOrderingFeature } from '@tanstack/svelte-table'
import type { ColumnOrderState } from '@tanstack/svelte-table'
const features = tableFeatures({ columnOrderingFeature })
const columnOrderAtom = createAtom<ColumnOrderState>([
'columnId1',
'columnId2',
'columnId3',
])
const columnOrder = useSelector(columnOrderAtom) // subscribe wherever it is needed
const table = createTable({
features,
//...
atoms: {
columnOrder: columnOrderAtom,
},
//...
})Alternatively, the v8-style state.columnOrder plus onColumnOrderChange pattern is still supported. It can be convenient for simple integrations or when migrating v8 code, but it is less fine-grained than external atoms. See the Table State Guide for a deeper comparison.
import { createTableState } from '@tanstack/svelte-table'
const features = tableFeatures({ columnOrderingFeature })
const [columnOrder, setColumnOrder] = createTableState<ColumnOrderState>([
'columnId1',
'columnId2',
'columnId3',
])
const table = createTable({
features,
//...
state: {
get columnOrder() {
return columnOrder()
},
},
onColumnOrderChange: setColumnOrder,
})import { createTableState } from '@tanstack/svelte-table'
const features = tableFeatures({ columnOrderingFeature })
const [columnOrder, setColumnOrder] = createTableState<ColumnOrderState>([
'columnId1',
'columnId2',
'columnId3',
])
const table = createTable({
features,
//...
state: {
get columnOrder() {
return columnOrder()
},
},
onColumnOrderChange: setColumnOrder,
})If the table has UI that allows the user to reorder columns, hook the drop event of your drag-and-drop solution up to table.setColumnOrder. It accepts either a new array of column ids or an updater function, so a drop handler usually just moves the dragged column id within the previous order:
// reorder columns after drag & drop
function handleDrop(movingColumnId: string, targetColumnId: string) {
table.setColumnOrder((prevColumnOrder) => {
const newColumnOrder = [...prevColumnOrder]
newColumnOrder.splice(
newColumnOrder.indexOf(targetColumnId),
0,
newColumnOrder.splice(newColumnOrder.indexOf(movingColumnId), 1)[0]!,
)
return newColumnOrder
})
}// reorder columns after drag & drop
function handleDrop(movingColumnId: string, targetColumnId: string) {
table.setColumnOrder((prevColumnOrder) => {
const newColumnOrder = [...prevColumnOrder]
newColumnOrder.splice(
newColumnOrder.indexOf(targetColumnId),
0,
newColumnOrder.splice(newColumnOrder.indexOf(movingColumnId), 1)[0]!,
)
return newColumnOrder
})
}table.setColumnOrder works the same whether the table manages the columnOrder state internally, you control it with state + onColumnOrderChange, or you own it with an external atom. The official Column Ordering example demonstrates reordering with table.setColumnOrder (it shuffles the columns rather than wiring up drag-and-drop).
Use table.setColumnOrder to update the column order state directly. Use table.resetColumnOrder to reset the order to initialState.columnOrder, or pass true to clear the order state.
table.setColumnOrder(['lastName', 'firstName', 'age'])
table.resetColumnOrder()
table.resetColumnOrder(true)table.setColumnOrder(['lastName', 'firstName', 'age'])
table.resetColumnOrder()
table.resetColumnOrder(true)Columns expose helpers for reading their current position after column pinning, manual ordering, and grouping have been applied.
column.getIndex()
column.getIndex('left')
column.getIndex('center')
column.getIndex('right')
column.getIsFirstColumn()
column.getIsLastColumn()column.getIndex()
column.getIndex('left')
column.getIndex('center')
column.getIndex('right')
column.getIsFirstColumn()
column.getIsLastColumn()These helpers are useful for styling column boundaries or building drag-and-drop targets that need to know the current rendered order.
TanStack Table is not opinionated about which drag-and-drop solution you use, and this repository does not currently include an official Svelte column drag-and-drop example. Here are a few suggestions:
Consider native browser drag events (ondragstart, ondragenter, ondragend) with a little $state of your own if you want zero dependencies. Svelte's inline event handlers make this approach very lightweight, but you will need to do extra work for proper touch support on mobile.
svelte-dnd-action is a popular Svelte-native drag-and-drop library built around an action you attach with use:dndzone. Check how well it handles semantic <table> markup for your use case before committing.
Atlassian's Pragmatic drag and drop is framework-agnostic, actively maintained, and works with Svelte. Avoid React-only DnD libraries (including DnD Kit's React packages); they depend on React's component model and do not work in Svelte apps.
Whichever solution you choose, the table-side integration is the same: call table.setColumnOrder from your drop handler as shown above.