Svelte Reactive Table ALPHA
v0.6.1
GitHub GitHub

Filtering

The filtering plugin provides powerful, flexible data filtering with an intuitive API. Filter by exact matches, multiple values, custom predicates, or use built-in helpers for common patterns like ranges and text matching.

Enable Filtering

Add filtering using the reactiveFiltering plugin:

<script lang="ts">
	import { reactiveTable, reactiveFiltering } from 'svelte-reactive-table';

	const data = [
		{ id: 1, name: 'Alice', age: 28, city: 'New York', status: 'active' },
		{ id: 2, name: 'Bob', age: 35, city: 'Los Angeles', status: 'inactive' },
		{ id: 3, name: 'Charlie', age: 22, city: 'Chicago', status: 'pending' }
	];

	const columns = [
		{ accessor: 'id', header: 'ID', isIdentifier: true },
		{ accessor: 'name', header: 'Name' },
		{ accessor: 'age', header: 'Age' },
		{ accessor: 'city', header: 'City' },
		{ accessor: 'status', header: 'Status' }
	];

	// Create table instance with filtering
	const table = reactiveTable(data, columns).use(reactiveFiltering());

	// Access filtering controls through plugins
	const { filtering } = table.plugins;
</script>

The table.rows property automatically contains only rows that match all active filters.

Filter Types

The filtering plugin supports three types of filters, automatically detected based on the value you provide:

Exact Match Filtering

Filter by exact equality for strings, numbers, or other values:

<script>
	// Filter by exact city match
	filtering.setFilter('city', 'New York');

	// Filter by exact status
	filtering.setFilter('status', 'active');

	// Filter by exact age
	filtering.setFilter('age', 28);
</script>

Array Filtering (IN Operation)

Provide an array to match any of the values (like SQL’s IN operator):

<script>
	// Filter for multiple cities
	filtering.setFilter('city', ['New York', 'Chicago']);

	// Filter for multiple statuses
	filtering.setFilter('status', ['active', 'pending']);
</script>

Predicate Function Filtering

Use a custom function for complex filtering logic:

<script>
	// Filter by age range
	filtering.setFilter('age', (age) => age >= 25 && age <= 35);

	// Filter by name length
	filtering.setFilter('name', (name) => name.length > 5);

	// Filter by complex conditions
	filtering.setFilter('email', (email) => email.endsWith('@company.com'));
</script>

String Filtering

String filters are special - they perform substring matching (contains) by default:

<script>
	// Matches any name containing "alice" (case-insensitive)
	filtering.setFilter('name', 'alice');
	// Matches: "Alice", "Alice Johnson", "alice smith", etc.

	// Matches any city containing "york"
	filtering.setFilter('city', 'york');
	// Matches: "New York", "York", "Yorkshire", etc.
</script>

String matching is case-insensitive by default. You can enable case-sensitive matching:

<script>
	const table = reactiveTable(data, columns).use(
		reactiveFiltering({
			caseSensitive: true
		})
	);

	// Now 'alice' won't match 'Alice'
	filtering.setFilter('name', 'alice');
</script>

Filter Helpers

The plugin includes helper functions for common filtering patterns:

Range Filter

Perfect for numbers, dates, or any comparable values:

<script>
	import { filterHelpers } from 'svelte-reactive-table';

	// Age between 25 and 35 (inclusive)
	filtering.setFilter('age', filterHelpers.range(25, 35));

	// Age 25 or higher (no max)
	filtering.setFilter('age', filterHelpers.range(25, undefined));

	// Age 35 or lower (no min)
	filtering.setFilter('age', filterHelpers.range(undefined, 35));

	// Date range
	filtering.setFilter(
		'createdAt',
		filterHelpers.range(new Date('2024-01-01'), new Date('2024-12-31'))
	);
</script>

Text Pattern Helpers

Match text patterns with precision:

<script>
	import { filterHelpers } from 'svelte-reactive-table';

	// Exact text match (case-sensitive)
	filtering.setFilter('name', filterHelpers.exactText('Alice'));

	// Starts with (case-insensitive by default)
	filtering.setFilter('name', filterHelpers.startsWith('A'));

	// Ends with
	filtering.setFilter('email', filterHelpers.endsWith('@company.com'));

	// Case-sensitive starts with
	filtering.setFilter('name', filterHelpers.startsWith('A', true));
</script>

NOT Filter

Invert any filter condition:

<script>
	import { filterHelpers } from 'svelte-reactive-table';

	// Not in New York
	filtering.setFilter('city', filterHelpers.not('New York'));

	// Not active or inactive
	filtering.setFilter('status', filterHelpers.not(['active', 'inactive']));

	// Not in age range
	filtering.setFilter('age', filterHelpers.not(filterHelpers.range(18, 25)));
</script>

Multiple Filters

Multiple filters use AND logic - rows must match all filters to appear:

<script>
	// Set multiple filters at once
	filtering.setFilters({
		city: 'New York',
		status: 'active',
		age: filterHelpers.range(25, 35)
	});

	// Or set filters individually
	filtering.setFilter('city', 'New York');
	filtering.setFilter('status', 'active');
	// Both filters must match
</script>

Managing Filter State

The plugin provides methods to control filter state:

Set and Remove Filters

<script>
	// Set a single filter
	filtering.setFilter('city', 'New York');

	// Set multiple filters
	filtering.setFilters({
		city: 'New York',
		status: 'active'
	});

	// Remove a specific filter
	filtering.removeFilter('city');

	// Clear all filters
	filtering.clearFilters();

	// Get current filter value
	const cityFilter = filtering.getFilter('city');
</script>

Empty Values Auto-Remove

Filters are automatically removed when set to empty values:

<script>
	// These all remove the filter:
	filtering.setFilter('city', undefined);
	filtering.setFilter('city', null);
	filtering.setFilter('city', '');
	filtering.setFilter('city', []);
</script>

Reactive Filter State

Access reactive properties to monitor filter state:

<script>
	// Number of active filters
	const filterCount = filtering.count;

	// Whether any filters are active
	const hasFilters = filtering.hasActiveFilters;

	// All current filters (read-only)
	const currentFilters = filtering.filters;
</script>

<!-- Show filter status in UI -->
{#if filtering.hasActiveFilters}
	<div class="filter-status">
		{filtering.count} filter{filtering.count === 1 ? '' : 's'} active
		<button onclick={() => filtering.clearFilters()}>Clear All</button>
	</div>
{/if}

Complete Filter UI Example

Here’s a practical example combining multiple filter types:

<script lang="ts">
	import { reactiveTable, reactiveFiltering, filterHelpers } from 'svelte-reactive-table';

	const table = reactiveTable(data, columns).use(reactiveFiltering());
	const { filtering } = table.plugins;

	// Reactive form state
	let nameSearch = $state('');
	let selectedCities = $state<string[]>([]);
	let minAge = $state<number | undefined>();
	let maxAge = $state<number | undefined>();

	// Sync filters with form state
	$effect(() => {
		filtering.setFilter('name', nameSearch.trim());
	});

	$effect(() => {
		filtering.setFilter('city', selectedCities);
	});

	$effect(() => {
		filtering.setFilter('age', filterHelpers.range(minAge, maxAge));
	});
</script>

<!-- Filter Controls -->
<div class="filters">
	<input type="text" bind:value={nameSearch} placeholder="Search names..." />

	<div>
		{#each cities as city}
			<label>
				<input type="checkbox" value={city} bind:group={selectedCities} />
				{city}
			</label>
		{/each}
	</div>

	<input type="number" bind:value={minAge} placeholder="Min age" />
	<input type="number" bind:value={maxAge} placeholder="Max age" />

	{#if filtering.hasActiveFilters}
		<button
			onclick={() => {
				filtering.clearFilters();
				nameSearch = '';
				selectedCities = [];
				minAge = undefined;
				maxAge = undefined;
			}}
		>
			Clear Filters ({filtering.count})
		</button>
	{/if}
</div>

<!-- Results Summary -->
<div class="results">
	Showing {table.rows.length} of {table.allRows.length} results
	{#if filtering.hasActiveFilters}
		<span>(filtered)</span>
	{/if}
</div>

<!-- Table -->
<table>
	<tbody>
		{#each table.rows as row}
			<tr>
				{#each row.cells as cell}
					<td>{cell.value}</td>
				{/each}
			</tr>
		{/each}
		{#if table.rows.length === 0 && filtering.hasActiveFilters}
			<tr>
				<td colspan={table.columns.length}> No results match your filters </td>
			</tr>
		{/if}
	</tbody>
</table>

Integration with Other Plugins

Filtering works seamlessly with other plugins:

<script>
	import {
		reactiveTable,
		reactiveFiltering,
		reactiveSorting,
		reactivePagination
	} from 'svelte-reactive-table';

	// Filters are applied first, then sorting, then pagination
	const table = reactiveTable(data, columns)
		.use(reactiveFiltering())
		.use(reactiveSorting())
		.use(reactivePagination({ pageSize: 10 }));

	// table.rows contains: filtered → sorted → paginated results
	// table.allRows contains: all data (useful for "showing X of Y")
</script>

When combined with pagination:

  • Pagination automatically resets to page 0 when filters change
  • Page counts update based on filtered results
  • table.rows shows the current page of filtered results
  • table.allRows shows all data before filtering

Initial Filters

Set filters when creating the table:

<script>
	const table = reactiveTable(data, columns).use(
		reactiveFiltering({
			initialFilters: {
				status: 'active',
				city: ['New York', 'Chicago']
			}
		})
	);
</script>

Automatic Updates

The filtering system automatically:

  • Re-filters when data items change
  • Re-filters when filter values change
  • Updates count and hasActiveFilters properties
  • Works reactively with Svelte 5’s $state and $derived

API Reference

For complete property and method documentation, see the reactiveFiltering API reference.