Client Processing
The table sorts, filters, searches and pages your rows in the browser. Pass an array, and every control on the page works.
Hand over the rows
processing: 'client' means the table does the work.
Search, filters, sorting, grouping and paging all happen in the browser, on the array you
passed. The items prop is the short way to say it:
An array and some columns
Employee | Role | Department | Location |
|---|---|---|---|
Emma Wilson | Staff Engineer | Platform | Berlin |
Liam Chen | Product Designer | Design | Hamburg |
Sofia Martinez | Engineering Manager | Platform | Munich |
James Park | Frontend Developer | Product | Remote |
Aisha Patel | Data Scientist | Data | Berlin |
<script lang="ts">
import { Table } from '@urbicon-ui/table';
import { employees } from './data';
const columns = [
{ accessor: 'name', title: 'Employee' },
{ accessor: 'role', title: 'Role' },
{ accessor: 'department', title: 'Department', groupable: true },
{ accessor: 'location', title: 'Location' }
];
</script>
<Table {columns} items={employees} viewDefaults={{ pageSize: 5 }} />Every column sorts and answers the search field unless it opts out; groupable is the one you opt into (Column Configuration). viewDefaults sets where the view the table owns
starts. Once that state has to live somewhere the reader can share, hand in a view of your own from createTableView instead (URL State); a table takes one or the other, never both.
You don't need source for this. Reach for it once a loading
or an error state comes into it.
Rows that arrive with the page are the same case. A SvelteKit load has them ready before the page renders, so the first
screen is server-rendered and the table takes over from there:
Every row, in one load
// +page.server.ts
export const load = async () => ({ employees: await db.employees.findMany() });
// +page.svelte
<script lang="ts">
import { Table } from '@urbicon-ui/table';
import { columns } from './columns';
let { data } = $props();
</script>
<Table {columns} items={data.employees} />While the rows are loading
When you fetch the rows yourself, source carries the two
states the table renders for you:
Your fetch, the table's states
<script lang="ts">
import { Table } from '@urbicon-ui/table';
let items = $state<Employee[]>([]);
let loading = $state(true);
let error = $state<string | null>(null);
fetchEmployees()
.then((rows) => (items = rows))
.catch((e) => (error = e.message))
.finally(() => (loading = false));
</script>
<Table {columns} source={{ processing: 'client', items, loading, error }} />The table shows its loading row while loading is
true, in place of the rows and with the pager hidden until it clears. Its error state
carries whatever error holds as the message. You decide
when each applies; the search field and the rest of the toolbar stay put throughout.
source wins over items
Both props reach the same rows. When you pass both, the table readssource and the items prop does nothing.When the browser runs out
The whole set sits in memory, and every sort touches all of it. A few thousand rows is comfortable. A hundred thousand is a tab that stops responding.
Two ways out, and they answer different questions. If the rows still fit and only the rendering hurts, keep client processing and draw fewer of them: Virtual Scrolling. If the set is too large to send at all, the backend sorts and pages it instead: Server Processing.