Skip to main content

Filtering

Filters use Zod schemas for validation and SuperForms for form handling. Filter state is persisted in URL params by default.

Setup

1. Define a filter schema

import { z } from 'zod/v4';

const filterSchema = z.object({
name: z.string().optional(),
status: z.enum(['active', 'inactive']).optional(),
createdAt: z.date().optional(),
});

2. Create a SuperForm on the server

import { superValidate } from 'sveltekit-superforms/server';
import { zod4 } from 'sveltekit-superforms/adapters';

// In +page.server.ts (metadata only -- no data loading)
export const load = async () => {
const filterForm = await superValidate(zod4(filterSchema));
return { filterForm };
};

3. Pass to useDataGrid

<script lang="ts">
import { DataGrid, useDataGrid } from '@repo/table';

const { data } = $props();

const { table, dataGrid } = useDataGrid({
tableOptions: { columns: [...] },
data: { data: data.users, count: data.totalCount },
filterSchema,
filterForm: data.filterForm,
});
</script>

4. Render filter fields via snippet

<DataGrid {dataGrid} {table} title="Users">
{#snippet filterFields()}
<!-- Your filter form fields here -->
<input type="text" name="name" placeholder="Search by name" />
<select name="status">
<option value="">All</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
{/snippet}
</DataGrid>

The DataGrid component renders a filter button. Clicking it opens a sidebar with your filterFields snippet.

FilterStrategy Interface

interface FilterStrategy {
get: <T extends z.ZodType>(options: { url?: URL; schema: T }) => z.infer<T>;
set: <T extends z.ZodType>(options: {
data: z.infer<T>;
options: OnResultOptions;
schema: T;
}) => MaybePromise<void>;
}

The default urlFilterStrategy encodes filters as URL params: ?filters=name:Alice,status:active.

Custom Filter Strategy

Use getURLFilterStrategy with custom serializers:

import { getURLFilterStrategy } from '@repo/table';

const customFilterStrategy = getURLFilterStrategy({
serialize: (data) => ({ /* custom serialization */ }),
deserialize: (params) => ({ /* custom deserialization */ }),
});

Or implement FilterStrategy from scratch. See Custom Strategies.