Row sorting
Sorting is a feature you opt into. Try it live - click any column
header to cycle none → asc → desc → none; shift-click adds the
column to the sort key list (multi-sort):
Open the live example: Sort, filter, paginate (Filtering & Search)
The examples on this page run against these rows:
<script lang="ts">
import { SvGrid } from '@svgrid/grid'
type Person = {
id: number
name: string
email: string
department: string
age: number
salary: number
city: string
startDate: string
active: boolean
}
const people: Person[] = [
{ id: 1, name: 'Ada Lovelace', email: '[email protected]', department: 'Engineering', age: 36, salary: 142000, city: 'London', startDate: '2021-03-01', active: true },
{ id: 2, name: 'Grace Hopper', email: '[email protected]', department: 'Engineering', age: 45, salary: 168000, city: 'New York', startDate: '2019-07-15', active: true },
{ id: 3, name: 'Linus Torvalds', email: '[email protected]', department: 'Platform', age: 54, salary: 155000, city: 'Portland', startDate: '2020-01-20', active: false },
{ id: 4, name: 'Radia Perlman', email: '[email protected]', department: 'Networking', age: 49, salary: 161000, city: 'Seattle', startDate: '2022-09-05', active: true },
{ id: 5, name: 'Barbara Liskov', email: '[email protected]', department: 'Platform', age: 52, salary: 172000, city: 'Boston', startDate: '2018-11-11', active: true },
]
const data = people
</script>
<script lang="ts">
import {
SvGrid, tableFeatures, rowSortingFeature, type ColumnDef,
} from '@svgrid/grid'
const features = tableFeatures({ rowSortingFeature })
const columns: ColumnDef<typeof features, Person>[] = [
{ field: 'firstName', header: 'First name', editorType: 'text' },
{ field: 'age', header: 'Age', editorType: 'number' },
{ field: 'joinedAt', header: 'Joined', editorType: 'date' },
]
</script>
<SvGrid {data} {columns} features={features} />
Clicking a sortable header toggles none → asc → desc → none. Shift-click
adds the column to the sort key list (multi-sort).
Sort functions
sortFns exposes the built-in comparators:
import { sortFns } from '@svgrid/grid'
// sortFns.auto - lexical (default for unknown types)
// sortFns.number - numeric, NaN-safe
// sortFns.date - Date-parsed
The grid picks the comparator based on the column's editorType:
| editorType | comparator |
|---|---|
'number' |
sortFns.number |
'date' | 'datetime' |
sortFns.date |
| anything else | sortFns.auto |
If your column has a non-trivial type, set editorType even if you do not
want inline editing - it is what tells sort and filter how to behave.
Programmatic sort
api.setSort('age', 'desc') // sort by age descending
api.setSort('age', null) // clear sort on this column
api.clearSort() // clear all sort
setSort replaces any existing sort with a single clause. For
multi-column sort, the user clicks the second column header with
Shift held (the in-grid affordance). A multi-sort setter on the API
is tracked in Missing features.
To observe sort changes from outside the grid:
<SvGrid
data={rows}
columns={columns}
features={features}
onSortingChange={(next) => (sorting = next)}
/>
Disable sort per column
Not yet first-class - there is no enableSorting: false field. To
prevent a column from being sortable, omit rowSortingFeature from
tableFeatures(...), or render a custom header via header: () => renderSnippet(...) that doesn't bind to the sort button.
Sorting + server-side data
When sort happens on the backend, pair externalSort={true} with
onSortingChange and round-trip the sort clauses through your
fetcher. See the 09-server-side demo.
Multi-column sort
Shift-click a second header and the sort becomes ordered: department first, then salary within it. The order you click is the order applied, which is why the header shows a position number once more than one is active.
<script lang="ts">
import { SvGrid, type GridColumns, type SvGridApi } from '@svgrid/grid'
type Person = {
id: number
name: string
department: string
city: string
salary: number
bio: string
}
const seed: Person[] = [
{ id: 1, name: 'Ada Lovelace', department: 'Engineering', city: 'London', salary: 142000,
bio: 'Wrote the first algorithm intended for a machine, and the first account of what a general-purpose computer could do beyond arithmetic.' },
{ id: 2, name: 'Grace Hopper', department: 'Engineering', city: 'New York', salary: 168000,
bio: 'Built the first compiler and argued that programs should be written in something closer to English than to machine code.' },
{ id: 3, name: 'Linus Torvalds', department: 'Platform', city: 'Portland', salary: 155000,
bio: 'Wrote a kernel and, later, the version control system that most of the industry now runs on.' },
]
const columns: GridColumns<Person> = [
{ field: 'department', header: 'Department', width: 170 },
{ field: 'name', header: 'Name', width: 180 },
{ field: 'salary', header: 'Salary', width: 140,
format: { type: 'currency', currency: 'USD' } },
]
</script>
<SvGrid data={seed} {columns} sortable />
Reading the sort model
onSortingChange reports the model as an ordered array, which is exactly the
shape you persist to a URL or hand to a server.
<script lang="ts">
import { SvGrid, type GridColumns, type SvGridApi } from '@svgrid/grid'
type Person = {
id: number
name: string
department: string
city: string
salary: number
bio: string
}
const seed: Person[] = [
{ id: 1, name: 'Ada Lovelace', department: 'Engineering', city: 'London', salary: 142000,
bio: 'Wrote the first algorithm intended for a machine, and the first account of what a general-purpose computer could do beyond arithmetic.' },
{ id: 2, name: 'Grace Hopper', department: 'Engineering', city: 'New York', salary: 168000,
bio: 'Built the first compiler and argued that programs should be written in something closer to English than to machine code.' },
{ id: 3, name: 'Linus Torvalds', department: 'Platform', city: 'Portland', salary: 155000,
bio: 'Wrote a kernel and, later, the version control system that most of the industry now runs on.' },
]
let model = $state('[]')
const columns: GridColumns<Person> = [
{ field: 'name', header: 'Name', width: 190 },
{ field: 'city', header: 'City', width: 150 },
{ field: 'salary', header: 'Salary', width: 140,
format: { type: 'currency', currency: 'USD' } },
]
</script>
<SvGrid
data={seed}
{columns}
sortable
onSortingChange={(s) => (model = JSON.stringify(s))}
/>
<p>Sort model: <code>{model}</code></p>
See also
Live examples
- Sort, filter, paginate - Three most-asked-for features wired together against ~5k rows.
- Server-side data - Sort/filter/page round-tripped to a mock endpoint with debounce + cancel.
Related articles
- Inside SvGrid: The Row Model and Sorting - How sorting shaped SvGrid's row-model pipeline - the decisions made early that every later feature inherited.
- Multi-Column Sorting in a Svelte Data Grid - How multi-column sorting works in SvGrid, from click behavior and sort priority to server-side ordering and programmatic control via the API.
- Server-Side Data - Pagination, Sorting, and Filtering on the Backend - Keep 100,000+ rows on the server. SvGrid owns the UI state for sort, filter, and pagination controls - your API owns the data.