Summary rows
Summary rows show totals, averages and other aggregates. Put them at the top or bottom; keep them pinned outside the scroll area, or let them scroll with…
Live demoSummary rows
Totals and averages at the top or bottom, pinned or scrolling.
Code for this demo
import { createGrid, type SummaryOptions } from '@freegridjs/core';
import { demoColumns, makeRows } from '../data';
import { search, select, tr, type DemoContext } from '../ui';
export default function mount(ctx: DemoContext) {
const { lang } = ctx;
const quarters = { q1: 'sum', q2: 'sum', q3: 'sum', q4: 'sum', total: 'sum' } as const;
let summary: SummaryOptions = {
position: 'bottom',
pinned: true,
scope: 'filtered',
rows: [
{ label: tr(lang, { en: 'Total', ko: '합계' }), columns: { ...quarters, id: 'count' } },
{
label: tr(lang, { en: 'Average', ko: '평균' }),
columns: { q1: 'avg', q2: 'avg', q3: 'avg', q4: 'avg', total: 'avg', growth: { agg: 'avg', format: '0.0%' } },
},
{
label: tr(lang, { en: 'Range', ko: '범위' }),
columns: {
total: { agg: 'max', prefix: tr(lang, { en: 'max', ko: '최대' }) },
country: values => tr(lang, { en: `${new Set(values).size} countries`, ko: `${new Set(values).size}개 국가` }),
},
},
],
};
const grid = createGrid(ctx.host, { columns: demoColumns(lang), data: makeRows(10_000), rowSelection: 'multiple', locale: lang, summary });
const update = (patch: Partial<SummaryOptions>) => {
summary = { ...summary, ...patch };
grid.setSummary(summary);
ctx.log(`setSummary → position: ${summary.position}, pinned: ${summary.pinned}, scope: ${summary.scope}`);
};
select(ctx, tr(lang, { en: 'Position', ko: '위치' }), [['bottom', tr(lang, { en: 'Bottom', ko: '하단' })], ['top', tr(lang, { en: 'Top', ko: '상단' })]], 'bottom',
v => update({ position: v }));
select(ctx, tr(lang, { en: 'Mode', ko: '방식' }), [['pinned', tr(lang, { en: 'Pinned', ko: '고정' })], ['scroll', tr(lang, { en: 'Scrolls with rows', ko: '스크롤과 함께' })]], 'pinned',
v => update({ pinned: v === 'pinned' }));
select(ctx, tr(lang, { en: 'Rows', ko: '집계 대상' }), [
['filtered', tr(lang, { en: 'Filtered rows', ko: '필터된 행' })],
['all', tr(lang, { en: 'All rows', ko: '전체 행' })],
['selected', tr(lang, { en: 'Selected rows', ko: '선택한 행' })],
], 'filtered', v => update({ scope: v }));
search(ctx, tr(lang, { en: 'Filter, e.g. "japan"', ko: '필터 예: "japan"' }), q => grid.setQuickFilter(q));
return grid;
}Summary rows show totals, averages and other aggregates. Put them at the top or bottom; keep them pinned outside the scroll area, or let them scroll with the data. They recalculate when data, filters or (with scope: 'selected') the selection change, and use each column's format unless a cell sets its own.
createGrid(el, {
columns,
data,
summary: {
position: 'bottom', // 'top' | 'bottom'
pinned: true, // true: fixed; false: scrolls with the rows
scope: 'filtered', // 'filtered' | 'all' | 'selected'
rows: [
{ label: 'Total', columns: { qty: 'sum', amount: 'sum', id: 'count' } },
{ label: 'Average', columns: { amount: { agg: 'avg', format: '#,##0.0' } } },
{ columns: {
amount: { agg: 'max', prefix: 'max' },
country: values => `${new Set(values).size} countries`, // custom
} },
],
},
});
grid.setSummary({ position: 'top', rows: [...] }); // change at runtime
grid.setSummary(null); // remove
grid.getSummaryValues(); // [{ qty: 1234, amount: 99000, id: 50 }, …]sum,avg,min,maxuse numeric values and skip blanks;min/maxalso compare dates.countis the number of rows in scope.- A function receives the column's values and the rows; return a number to have it formatted, or a string to show as is.
- The row
labelappears in the first visible column without an aggregate in that row.