Skip to content

Commit 1b51ade

Browse files
authored
Merge pull request #95 from blerrgh/server_side
Basic server-side query support
2 parents d941454 + 6b37199 commit 1b51ade

File tree

7 files changed

+101
-47
lines changed

7 files changed

+101
-47
lines changed

package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "svelte-headless-table",
33
"description": "Unopinionated and extensible data tables for Svelte",
4-
"version": "0.16.2",
4+
"version": "0.17.0",
55
"scripts": {
66
"dev": "vite dev",
77
"build": "vite build",

src/lib/plugins/addColumnFilters.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { derived, writable, type Readable, type Writable } from 'svelte/store';
66
import type { PluginInitTableState } from '../createViewModel';
77
import type { DataBodyCell } from '../bodyCells';
88

9+
export interface ColumnFiltersConfig {
10+
serverSide?: boolean;
11+
}
12+
913
export interface ColumnFiltersState<Item> {
1014
filterValues: Writable<Record<string, unknown>>;
1115
preFilteredRows: Readable<BodyRow<Item>[]>;
@@ -89,7 +93,7 @@ const getFilteredRows = <Item, Row extends BodyRow<Item>>(
8993
};
9094

9195
export const addColumnFilters =
92-
<Item>(): TablePlugin<
96+
<Item>({ serverSide = false }: ColumnFiltersConfig = {}): TablePlugin<
9397
Item,
9498
ColumnFiltersState<Item>,
9599
ColumnFiltersColumnOptions<Item>,
@@ -105,9 +109,14 @@ export const addColumnFilters =
105109
const deriveRows: DeriveRowsFn<Item> = (rows) => {
106110
return derived([rows, filterValues], ([$rows, $filterValues]) => {
107111
preFilteredRows.set($rows);
108-
const _filteredRows = getFilteredRows($rows, $filterValues, columnOptions);
109-
filteredRows.set(_filteredRows);
110-
return _filteredRows;
112+
if (!serverSide) {
113+
const _filteredRows = getFilteredRows($rows, $filterValues, columnOptions);
114+
filteredRows.set(_filteredRows);
115+
return _filteredRows;
116+
} else {
117+
filteredRows.set($rows);
118+
return $rows;
119+
}
111120
});
112121
};
113122

src/lib/plugins/addPagination.ts

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,26 @@ import { derived, writable, type Readable, type Updater, type Writable } from 's
55
export interface PaginationConfig {
66
initialPageIndex?: number;
77
initialPageSize?: number;
8+
serverSide?: boolean;
89
}
910

1011
export interface PaginationState {
1112
pageSize: Writable<number>;
1213
pageIndex: Writable<number>;
1314
pageCount: Readable<number>;
15+
serverItemsCount: Writable<number>;
1416
hasPreviousPage: Readable<boolean>;
1517
hasNextPage: Readable<boolean>;
1618
}
1719

1820
const MIN_PAGE_SIZE = 1;
1921

20-
export const createPageStore = ({ items, initialPageSize, initialPageIndex }: PageStoreConfig) => {
22+
export const createPageStore = ({
23+
items,
24+
initialPageSize,
25+
initialPageIndex,
26+
serverSide,
27+
}: PageStoreConfig) => {
2128
const pageSize = writable(initialPageSize);
2229
const updatePageSize = (fn: Updater<number>) => {
2330
pageSize.update(($pageSize) => {
@@ -27,18 +34,27 @@ export const createPageStore = ({ items, initialPageSize, initialPageIndex }: Pa
2734
};
2835
const setPageSize = (newPageSize: number) => updatePageSize(() => newPageSize);
2936

30-
const pageCount = derived([pageSize, items], ([$pageSize, $items]) => {
31-
const $pageCount = Math.ceil($items.length / $pageSize);
37+
const pageIndex = writable(initialPageIndex);
38+
39+
function calcPageCountAndLimitIndex([$pageSize, $itemsCount]: [$pageSize: number, $itemsCount: number]) {
40+
const $pageCount = Math.ceil($itemsCount / $pageSize);
3241
pageIndex.update(($pageIndex) => {
3342
if ($pageCount > 0 && $pageIndex >= $pageCount) {
3443
return $pageCount - 1;
3544
}
3645
return $pageIndex;
3746
});
3847
return $pageCount;
39-
});
48+
}
4049

41-
const pageIndex = writable(initialPageIndex);
50+
const serverItemsCount = writable(0);
51+
let pageCount;
52+
if (serverSide) {
53+
pageCount = derived([pageSize, serverItemsCount], calcPageCountAndLimitIndex);
54+
} else {
55+
const itemCount = derived(items, ($items) => $items.length);
56+
pageCount = derived([pageSize, itemCount], calcPageCountAndLimitIndex);
57+
}
4258

4359
const hasPreviousPage = derived(pageIndex, ($pageIndex) => {
4460
return $pageIndex > 0;
@@ -53,8 +69,9 @@ export const createPageStore = ({ items, initialPageSize, initialPageIndex }: Pa
5369
update: updatePageSize,
5470
set: setPageSize,
5571
},
56-
pageCount,
5772
pageIndex,
73+
pageCount,
74+
serverItemsCount,
5875
hasPreviousPage,
5976
hasNextPage,
6077
};
@@ -64,10 +81,15 @@ export interface PageStoreConfig {
6481
items: Readable<unknown[]>;
6582
initialPageSize?: number;
6683
initialPageIndex?: number;
84+
serverSide?: boolean;
6785
}
6886

6987
export const addPagination =
70-
<Item>({ initialPageIndex = 0, initialPageSize = 10 }: PaginationConfig = {}): TablePlugin<
88+
<Item>({
89+
initialPageIndex = 0,
90+
initialPageSize = 10,
91+
serverSide = false,
92+
}: PaginationConfig = {}): TablePlugin<
7193
Item,
7294
PaginationState,
7395
Record<string, never>,
@@ -76,26 +98,34 @@ export const addPagination =
7698
() => {
7799
const prePaginatedRows = writable<BodyRow<Item>[]>([]);
78100
const paginatedRows = writable<BodyRow<Item>[]>([]);
79-
const { pageSize, pageCount, pageIndex, hasPreviousPage, hasNextPage } = createPageStore({
80-
items: prePaginatedRows,
81-
initialPageIndex,
82-
initialPageSize,
83-
});
101+
const { pageSize, pageIndex, pageCount, serverItemsCount, hasPreviousPage, hasNextPage } =
102+
createPageStore({
103+
items: prePaginatedRows,
104+
initialPageIndex,
105+
initialPageSize,
106+
serverSide,
107+
});
84108
const pluginState: PaginationState = {
85109
pageSize,
86110
pageIndex,
87111
pageCount,
112+
serverItemsCount,
88113
hasPreviousPage,
89114
hasNextPage,
90115
};
91116

92117
const derivePageRows: DeriveRowsFn<Item> = (rows) => {
93118
return derived([rows, pageSize, pageIndex], ([$rows, $pageSize, $pageIndex]) => {
94119
prePaginatedRows.set($rows);
95-
const startIdx = $pageIndex * $pageSize;
96-
const _paginatedRows = $rows.slice(startIdx, startIdx + $pageSize);
97-
paginatedRows.set(_paginatedRows);
98-
return _paginatedRows;
120+
if (!serverSide) {
121+
const startIdx = $pageIndex * $pageSize;
122+
const _paginatedRows = $rows.slice(startIdx, startIdx + $pageSize);
123+
paginatedRows.set(_paginatedRows);
124+
return _paginatedRows;
125+
} else {
126+
paginatedRows.set($rows);
127+
return $rows;
128+
}
99129
});
100130
};
101131

src/lib/plugins/addSortBy.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface SortByConfig {
1010
disableMultiSort?: boolean;
1111
isMultiSortEvent?: (event: Event) => boolean;
1212
toggleOrder?: ('asc' | 'desc' | undefined)[];
13+
serverSide?: boolean;
1314
}
1415

1516
const DEFAULT_TOGGLE_ORDER: ('asc' | 'desc' | undefined)[] = ['asc', 'desc', undefined];
@@ -168,6 +169,7 @@ export const addSortBy =
168169
disableMultiSort = false,
169170
isMultiSortEvent = isShiftClick,
170171
toggleOrder,
172+
serverSide = false,
171173
}: SortByConfig = {}): TablePlugin<Item, SortByState<Item>, SortByColumnOptions, SortByPropSet> =>
172174
({ columnOptions }) => {
173175
const disabledSortIds = Object.entries(columnOptions)
@@ -176,18 +178,15 @@ export const addSortBy =
176178

177179
const sortKeys = createSortKeysStore(initialSortKeys);
178180
const preSortedRows = writable<BodyRow<Item>[]>([]);
179-
const sortedRows = writable<BodyRow<Item>[]>([]);
180181

181182
const deriveRows: DeriveRowsFn<Item> = (rows) => {
182183
return derived([rows, sortKeys], ([$rows, $sortKeys]) => {
183184
preSortedRows.set($rows);
184-
const _sortedRows = getSortedRows<Item, typeof $rows[number]>(
185-
$rows,
186-
$sortKeys,
187-
columnOptions
188-
);
189-
sortedRows.set(_sortedRows);
190-
return _sortedRows;
185+
if (serverSide) {
186+
return getSortedRows<Item, typeof $rows[number]>($rows, $sortKeys, columnOptions);
187+
} else {
188+
return $rows;
189+
}
191190
});
192191
};
193192

src/lib/plugins/addTableFilter.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface TableFilterConfig {
77
fn?: TableFilterFn;
88
initialFilterValue?: string;
99
includeHiddenColumns?: boolean;
10+
serverSide?: boolean;
1011
}
1112

1213
export interface TableFilterState<Item> {
@@ -106,6 +107,7 @@ export const addTableFilter =
106107
fn = textPrefixFilter,
107108
initialFilterValue = '',
108109
includeHiddenColumns = false,
110+
serverSide = false,
109111
}: TableFilterConfig = {}): TablePlugin<
110112
Item,
111113
TableFilterState<Item>,
@@ -115,7 +117,6 @@ export const addTableFilter =
115117
({ columnOptions }) => {
116118
const filterValue = writable(initialFilterValue);
117119
const preFilteredRows = writable<BodyRow<Item>[]>([]);
118-
const filteredRows = writable<BodyRow<Item>[]>([]);
119120
const tableCellMatches = recordSetStore();
120121

121122
const pluginState: TableFilterState<Item> = { filterValue, preFilteredRows };
@@ -131,8 +132,11 @@ export const addTableFilter =
131132
includeHiddenColumns,
132133
});
133134
tableCellMatches.set($tableCellMatches);
134-
filteredRows.set($filteredRows);
135-
return $filteredRows;
135+
if (serverSide) {
136+
return $rows;
137+
} else {
138+
return $filteredRows;
139+
}
136140
});
137141
};
138142

src/routes/+page.svelte

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,25 @@
3333
3434
const data = readable(createSamples(2, 2));
3535
36+
let serverSide = false;
37+
3638
const table = createTable(data, {
3739
subRows: addSubRows({
3840
children: 'children',
3941
}),
40-
filter: addColumnFilters(),
42+
filter: addColumnFilters({
43+
serverSide: serverSide,
44+
}),
4145
tableFilter: addTableFilter({
4246
includeHiddenColumns: true,
47+
serverSide: serverSide,
4348
}),
4449
group: addGroupBy({
4550
initialGroupByIds: [],
4651
}),
4752
sort: addSortBy({
4853
toggleOrder: ['asc', 'desc'],
54+
serverSide: serverSide,
4955
}),
5056
expand: addExpandedRows({
5157
initialExpandedIds: { 1: true },
@@ -57,6 +63,7 @@
5763
hideColumns: addHiddenColumns(),
5864
page: addPagination({
5965
initialPageSize: 20,
66+
serverSide: serverSide,
6067
}),
6168
resize: addResizedColumns(),
6269
export: addDataExport(),
@@ -258,7 +265,8 @@
258265
const { filterValues } = pluginStates.filter;
259266
const { filterValue } = pluginStates.tableFilter;
260267
const { selectedDataIds } = pluginStates.select;
261-
const { pageIndex, pageCount, pageSize, hasPreviousPage, hasNextPage } = pluginStates.page;
268+
const { pageIndex, pageCount, pageSize, hasPreviousPage, hasNextPage, serverItemCount } =
269+
pluginStates.page;
262270
const { expandedIds } = pluginStates.expand;
263271
const { columnIdOrder } = pluginStates.orderColumns;
264272
// $: $columnIdOrder = ['expanded', ...$groupByIds];
@@ -268,6 +276,8 @@
268276
const { exportedData } = pluginStates.export;
269277
const { exportedData: exportedJson } = pluginStates.exportJson;
270278
const { exportedData: exportedCsv } = pluginStates.exportCsv;
279+
280+
$serverItemCount = 6;
271281
</script>
272282

273283
<h1>svelte-headless-table</h1>
@@ -364,6 +374,7 @@
364374
groupByIds: $groupByIds,
365375
sortKeys: $sortKeys,
366376
filterValues: $filterValues,
377+
filterValue: $filterValue,
367378
selectedDataIds: $selectedDataIds,
368379
columnIdOrder: $columnIdOrder,
369380
hiddenColumnIds: $hiddenColumnIds,
@@ -372,7 +383,8 @@
372383
},
373384
null,
374385
2
375-
)}</pre>
386+
)}
387+
serverSide: {serverSide}</pre>
376388

377389
<style>
378390
* {

0 commit comments

Comments
 (0)