Pages & server data
Page through rows, or load them from your server in blocks as people scroll.
Code for this demo
import { createGrid, type ColumnDef, type GridApi, type GridOptions, type Row, type ServerParams } from '@freegridjs/core';
import { makeRows } from '../data';
import { button, separator, text, tr, type DemoContext } from '../ui';
type Mode = 'pages' | 'server' | 'infinite' | 'serverPages';
/** A pretend server in the browser: sorts, filters and answers after a short delay. */
function fakeServer(rows: Row[], log: (m: string) => void, knowsTotal = true) {
return {
getRows(p: ServerParams): Promise<{ rows: Row[]; total?: number }> {
let list = rows;
const q = p.quickFilter.trim().toLowerCase();
if (q) list = list.filter(r => `${r.name} ${r.company} ${r.country}`.toLowerCase().includes(q));
const s = p.sort[0];
if (s) {
const dir = s.dir === 'desc' ? -1 : 1;
list = [...list].sort((a, b) => (a[s.colId] < b[s.colId] ? -dir : a[s.colId] > b[s.colId] ? dir : 0));
}
log(`getRows → ${p.start}–${p.end}${s ? ` sort ${s.colId} ${s.dir}` : ''}${q ? ` "${q}"` : ''}`);
const page = list.slice(p.start, p.end);
return new Promise(resolve => setTimeout(() => resolve(knowsTotal ? { rows: page, total: list.length } : { rows: page }), 350));
},
};
}
export default function mount(ctx: DemoContext) {
const { lang } = ctx;
const h = (en: string, ko: string) => tr(lang, { en, ko });
const columns: ColumnDef[] = [
{ field: 'id', header: 'ID', type: 'number', width: 90 },
{ field: 'name', header: h('Name', '이름'), width: 170 },
{ field: 'company', header: h('Company', '회사'), width: 150 },
{ field: 'country', header: h('Country', '국가'), width: 150, filter: false },
{ field: 'total', header: h('Total', '합계'), type: 'number', format: '#,##0', width: 130 },
{ field: 'joined', header: h('Joined', '가입일'), type: 'date', width: 130 },
];
const big = makeRows(100000);
let grid: GridApi | null = null;
const show = (mode: Mode) => {
grid?.destroy();
const options: Partial<GridOptions> =
mode === 'pages' ? { data: makeRows(1000), pagination: { pageSize: 50, pageSizes: [20, 50, 100] } }
: mode === 'server' ? { datasource: fakeServer(big, ctx.log), blockSize: 100 }
: mode === 'infinite' ? { datasource: fakeServer(big, ctx.log, false), blockSize: 100 }
: { datasource: fakeServer(big, ctx.log), pagination: { pageSize: 50, pageSizes: [20, 50, 100] } };
// the pretend server only understands sorting and the quick search
const cols = mode === 'pages' ? columns : columns.map(c => ({ ...c, filter: false as const }));
grid = createGrid(ctx.host, { columns: cols, locale: lang, theme: 'erp', statusBar: true, ...options });
grid.on('pageChange', e => ctx.log(`pageChange → ${e.page + 1} / ${e.pageCount}`));
grid.on('rowsLoaded', e => ctx.log(`rowsLoaded → ${e.start}–${e.end}${e.total !== undefined ? ` of ${e.total}` : ''}`));
};
text(ctx, h('The server modes fetch 100 rows at a time from a pretend server with a short delay. Scroll fast to see the placeholders.',
'서버 모드는 지연이 있는 가짜 서버에서 100행씩 받아 옵니다. 빠르게 스크롤하면 불러오는 동안의 자리 표시를 볼 수 있습니다.'));
separator(ctx);
button(ctx, h('Pages (1,000 rows in the browser)', '페이지 (브라우저의 1,000행)'), () => show('pages'));
button(ctx, h('Server, 100,000 rows', '서버, 10만 행'), () => show('server'));
button(ctx, h('Infinite scroll', '무한 스크롤'), () => show('infinite'));
button(ctx, h('Server pages', '서버 페이지'), () => show('serverPages'));
separator(ctx);
button(ctx, h('Search "Kim" on the server', '서버에서 "Kim" 검색'), () => grid?.setQuickFilter('Kim'));
button(ctx, h('Clear search', '검색 지우기'), () => grid?.setQuickFilter(''));
button(ctx, h('Reload rows', '다시 불러오기'), () => grid?.refreshRows());
show('pages');
return grid;
}