# Sort, filter, paginate

Three most-asked-for features wired together against ~5k rows.

Uses `@svgrid/grid` (MIT). Category: Filtering & Search. Live demo: https://svgrid.com/demos/02-sort-filter-paginate/

Install: `npm i @svgrid/grid` (Svelte 5).

## About this example

Sorting, filtering and pagination wired together in the Svelte 5 data grid over 5,000 rows. Shift+click headers for multi-column sort, a per-column filter row for text and numbers, and a pagination footer with a page-size selector, from rowSortingFeature, columnFilteringFeature and rowPaginationFeature. The component owns the state so it can be persisted, here in the URL.

Three most-asked-for features wired together against a 5,000-row dataset.

- multi-column sort (shift-click headers)
- per-column filter row (text/number)
- pagination footer with page-size selector State is owned by this component so it can be persisted (here: in URL).

## Imports, features and API used

- Imports: `@svgrid/grid`, `../shared/seed`
- Table features registered: `rowSortingFeature`, `columnFilteringFeature`, `rowPaginationFeature`
- Columns: `firstName` (First name), `lastName` (Last name), `department` (Department), `country` (Country), `age` (Age), `salary` (Salary), `joinedAt` (Joined)

## Frequently asked questions

### How do I enable pagination?

Register rowPaginationFeature in features and set showPagination with a pageSize. The footer renders page controls and a page-size selector; the current page is grid state.

### How do I sort by more than one column?

Click a header to sort by it and Shift+click another to add it as a secondary key. The sort indicators show the order; clicking again cycles direction and off.

### How is the state kept in the URL?

The component holds sorting, filters and page in its own state, serializes them into the query string when they change and reads them back on load, so a link reproduces the same view.

## Related documentation

- [Column definitions](https://svgrid.com/docs/help/columns/column-definitions.md)
- [Applying filters](https://svgrid.com/docs/help/filtering/applying-filters.md)
- [Recipes / Cookbook](https://svgrid.com/docs/help/recipes.md)
- [Row pagination](https://svgrid.com/docs/help/rows/row-pagination.md)
- [Row sorting](https://svgrid.com/docs/help/rows/row-sorting.md)

## Related articles

- [Inside SvGrid: The Row Model and Sorting](https://svgrid.com/blog/building-the-sort-pipeline/) - 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](https://svgrid.com/blog/multi-column-sorting/) - How multi-column sorting works in SvGrid, from click behavior and sort priority to server-side ordering and programmatic control via the API.

## Source code (02-sort-filter-paginate.svelte)

```svelte
<!-- Documented in: docs/help/recipes.md -->
<script lang="ts">
  /**
   * 02. Sort · Filter · Paginate
   * ----------------------------
   * Three most-asked-for features wired together against a 5,000-row dataset.
   *   - multi-column sort (shift-click headers)
   *   - per-column filter row (text/number)
   *   - pagination footer with page-size selector
   * State is owned by this component so it can be persisted (here: in URL).
   */
  import {
    SvGrid,
    tableFeatures,
    rowSortingFeature,
    columnFilteringFeature,
    rowPaginationFeature,
    type GridColumns,
  } from '@svgrid/grid'
  import { makePeople, type Person } from '../shared/seed'

  const features = tableFeatures({
    rowSortingFeature,
    columnFilteringFeature,
    rowPaginationFeature,
  })

  const rows = makePeople(5_000)

  const columns: GridColumns<Person> = [
    { field: 'firstName',  header: 'First name', editorType: 'text' },
    { field: 'lastName',   header: 'Last name',  editorType: 'text' },
    { field: 'department', header: 'Department', editorType: 'text' },
    { field: 'country',    header: 'Country',    editorType: 'text' },
    { field: 'age',        header: 'Age',        editorType: 'number' },
    {
      field: 'salary',
      header: 'Salary',
      editorType: 'number',
      format: { type: 'currency', currency: 'USD', options: { maximumFractionDigits: 0 } },
    },
    {
      field: 'joinedAt',
      header: 'Joined',
      editorType: 'date',
      format: { type: 'date', pattern: 'y-m-d' },
    },
  ]
</script>

<section class="flex flex-col flex-1 min-h-0 gap-3">
  <div class="flex flex-wrap items-center gap-3 text-sm shrink-0">
    <span class="sfp-strong">{rows.length.toLocaleString()} rows</span>
    <span class="sfp-muted">·</span>
    <span class="sfp-muted">
      Click a header to sort. Shift+click to multi-sort. Type in the filter row.
    </span>
  </div>

  <div class="flex-1 min-h-0">
    <SvGrid responsive={true}
      columnResize
      data={rows}
      columns={columns}
      features={features}
      filterMode="row"
      selectionMode="none"
      showPagination={true}
      pageSize={50}
      showGroupingControls={false}
      enableInlineEditing={false}
      enableCellSelection={false}
      rowHeight={36}
      containerHeight="100%"
      fitColumns={true}
    />
  </div>
</section>

<style>
  .sfp-strong { color: var(--sg-fg, #475569); }
  .sfp-muted  { color: var(--sg-muted, #64748b); }
</style>
```

[View this example on GitHub](https://github.com/sv-grid/sv-grid/blob/main/examples/src/demos/02-sort-filter-paginate.svelte)
