Documentation
Aggregate Functions
Summarize grouped rows with sum, average, count, min, max, or a custom function.
Sum
Set aggregation: { type: "sum" } on a column. Aggregations run on grouped rows — you need row grouping.
TypeScript
Copy
{accessor: "budget",label: "Budget",type: "number",aggregation: { type: "sum" },}
TypeScript
Copy
{accessor: "budget",label: "Budget",type: "number",aggregation: { type: "sum" },}
TypeScript
Copy
{accessor: "budget",label: "Budget",type: "number",aggregation: { type: "sum" },}
TypeScript
Copy
{accessor: "budget",label: "Budget",type: "number",aggregation: { type: "sum" },}
TypeScript
Copy
{accessor: "budget",label: "Budget",type: "number",aggregation: { type: "sum" },}
TypeScript
Copy
{accessor: "budget",label: "Budget",type: "number",aggregation: { type: "sum" },}
Average
Arithmetic mean of values in each group.
TypeScript
Copy
{accessor: "rating",label: "Rating",type: "number",aggregation: { type: "average" },}
TypeScript
Copy
{accessor: "rating",label: "Rating",type: "number",aggregation: { type: "average" },}
TypeScript
Copy
{accessor: "rating",label: "Rating",type: "number",aggregation: { type: "average" },}
TypeScript
Copy
{accessor: "rating",label: "Rating",type: "number",aggregation: { type: "average" },}
TypeScript
Copy
{accessor: "rating",label: "Rating",type: "number",aggregation: { type: "average" },}
TypeScript
Copy
{accessor: "rating",label: "Rating",type: "number",aggregation: { type: "average" },}
Count
Counts non-null values in each group.
TypeScript
Copy
{accessor: "projects",label: "Projects",aggregation: { type: "count" },}
TypeScript
Copy
{accessor: "projects",label: "Projects",aggregation: { type: "count" },}
TypeScript
Copy
{accessor: "projects",label: "Projects",aggregation: { type: "count" },}
TypeScript
Copy
{accessor: "projects",label: "Projects",aggregation: { type: "count" },}
TypeScript
Copy
{accessor: "projects",label: "Projects",aggregation: { type: "count" },}
TypeScript
Copy
{accessor: "projects",label: "Projects",aggregation: { type: "count" },}
Min / max
Finds the minimum or maximum value in each group.
TypeScript
Copy
{accessor: "score",label: "Score",type: "number",aggregation: { type: "max" },}
TypeScript
Copy
{accessor: "score",label: "Score",type: "number",aggregation: { type: "max" },}
TypeScript
Copy
{accessor: "score",label: "Score",type: "number",aggregation: { type: "max" },}
TypeScript
Copy
{accessor: "score",label: "Score",type: "number",aggregation: { type: "max" },}
TypeScript
Copy
{accessor: "score",label: "Score",type: "number",aggregation: { type: "max" },}
TypeScript
Copy
{accessor: "score",label: "Score",type: "number",aggregation: { type: "max" },}
Parse and format values
Use parseValue when source data is formatted (e.g. currency strings), and formatResult to display the aggregate.
TypeScript
Copy
{accessor: "budget",label: "Budget",aggregation: {type: "sum",parseValue: (val) => parseFloat(String(val).replace(/[^0-9.-]/g, "")),formatResult: (val) => "$" + val.toLocaleString(),},}
TypeScript
Copy
{accessor: "budget",label: "Budget",aggregation: {type: "sum",parseValue: (val) => parseFloat(String(val).replace(/[^0-9.-]/g, "")),formatResult: (val) => "$" + val.toLocaleString(),},}
TypeScript
Copy
{accessor: "budget",label: "Budget",aggregation: {type: "sum",parseValue: (val) => parseFloat(String(val).replace(/[^0-9.-]/g, "")),formatResult: (val) => "$" + val.toLocaleString(),},}
TypeScript
Copy
{accessor: "budget",label: "Budget",aggregation: {type: "sum",parseValue: (val) => parseFloat(String(val).replace(/[^0-9.-]/g, "")),formatResult: (val) => "$" + val.toLocaleString(),},}
TypeScript
Copy
{accessor: "budget",label: "Budget",aggregation: {type: "sum",parseValue: (val) => parseFloat(String(val).replace(/[^0-9.-]/g, "")),formatResult: (val) => "$" + val.toLocaleString(),},}
TypeScript
Copy
{accessor: "budget",label: "Budget",aggregation: {type: "sum",parseValue: (val) => parseFloat(String(val).replace(/[^0-9.-]/g, "")),formatResult: (val) => "$" + val.toLocaleString(),},}
Custom aggregation
Set type: "custom" and provide customFn — it receives all values in the group.
TypeScript
Copy
{accessor: "performance",label: "Performance",aggregation: {type: "custom",customFn: (values) => {const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));if (nums.length === 0) return 0;return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10) / 10;},},}
TypeScript
Copy
{accessor: "performance",label: "Performance",aggregation: {type: "custom",customFn: (values) => {const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));if (nums.length === 0) return 0;return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10) / 10;},},}
TypeScript
Copy
{accessor: "performance",label: "Performance",aggregation: {type: "custom",customFn: (values) => {const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));if (nums.length === 0) return 0;return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10) / 10;},},}
TypeScript
Copy
{accessor: "performance",label: "Performance",aggregation: {type: "custom",customFn: (values) => {const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));if (nums.length === 0) return 0;return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10) / 10;},},}
TypeScript
Copy
{accessor: "performance",label: "Performance",aggregation: {type: "custom",customFn: (values) => {const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));if (nums.length === 0) return 0;return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10) / 10;},},}
TypeScript
Copy
{accessor: "performance",label: "Performance",aggregation: {type: "custom",customFn: (values) => {const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));if (nums.length === 0) return 0;return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10) / 10;},},}
Example
React TSX
Copy
1import {SimpleTable} from "@simple-table/react";import type { Theme } from "@simple-table/react";2import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";3import "@simple-table/react/styles.css";45const AggregateFunctionsDemo = ({6 height = "400px",7 theme,8}: {9 height?: string | number;10 theme?: Theme;11}) => {12 return (13 <SimpleTable14 columns={aggregateFunctionsConfig.headers}15 rows={aggregateFunctionsConfig.rows}16 rowGrouping={aggregateFunctionsConfig.tableProps.rowGrouping}17 columnResizing18 height={height}19 theme={theme}20 />21 );22};2324export default AggregateFunctionsDemo;
Vue SFC
Copy
1<template>2 <SimpleTable3 :columns="aggregateFunctionsConfig.headers"4 :rows="aggregateFunctionsConfig.rows"5 :row-grouping="aggregateFunctionsConfig.tableProps.rowGrouping"6 :column-resizing="true"7 :height="height"8 :theme="theme"9 />10</template>1112<script setup lang="ts">13import {SimpleTable} from "@simple-table/vue";import type { Theme } from "@simple-table/vue";14import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";15import "@simple-table/vue/styles.css";1617withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {18 height: "400px",19});20</script>
Angularaggregate-functions-demo.component.ts
Copy
1import { Component, Input } from "@angular/core";2import {SimpleTableComponent} from "@simple-table/angular";import type { AngularColumnDef, Row, Theme } from "@simple-table/angular";3import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";4import "@simple-table/angular/styles.css";56@Component({7 selector: "aggregate-functions-demo",8 standalone: true,9 imports: [SimpleTableComponent],10 template: `11 <simple-table12 [rows]="rows"13 [columns]="headers"14 [rowGrouping]="grouping"15 [columnResizing]="true"16 [height]="height"17 [theme]="theme"18 ></simple-table>19 `,20})21export class AggregateFunctionsDemoComponent {22 @Input() height: string | number = "400px";23 @Input() theme?: Theme;2425 readonly rows: Row[] = aggregateFunctionsConfig.rows;26 readonly headers: AngularColumnDef[] = aggregateFunctionsConfig.headers;27 readonly grouping = aggregateFunctionsConfig.tableProps.rowGrouping;28}293031// aggregate-functions.demo-data.ts32// Self-contained demo table setup for this example.33import type { AngularColumnDef } from "@simple-table/angular";343536export const aggregateFunctionsHeaders: AngularColumnDef[] = [37 { accessor: "name", label: "Name", width: 200, expandable: true, type: "string" },38 {39 accessor: "followers",40 label: "Followers",41 width: 120,42 type: "number",43 aggregation: { type: "sum" },44 valueFormatter: ({ value }) => {45 if (typeof value === "number") {46 return value >= 100000047 ? `${(value / 1000000).toFixed(1)}M`48 : value >= 100049 ? `${(value / 1000).toFixed(0)}K`50 : value.toString();51 }52 return "";53 },54 },55 {56 accessor: "revenue",57 label: "Monthly Revenue",58 width: 140,59 type: "string",60 aggregation: {61 type: "sum",62 parseValue: (value) => {63 if (typeof value !== "string") return 0;64 const numericValue = parseFloat(value.replace(/[$K]/g, ""));65 return isNaN(numericValue) ? 0 : numericValue;66 },67 },68 valueFormatter: ({ value }) => {69 if (typeof value === "number") return `$${value.toFixed(1)}K`;70 if (typeof value === "string") return value;71 return "";72 },73 },74 {75 accessor: "rating",76 label: "Rating",77 width: 100,78 type: "number",79 aggregation: { type: "average" },80 valueFormatter: ({ value }) => (typeof value === "number" ? `${value.toFixed(1)} ⭐` : ""),81 },82 {83 accessor: "contentCount",84 label: "Content",85 width: 90,86 type: "number",87 aggregation: { type: "sum" },88 },89 {90 accessor: "avgViewTime",91 label: "Avg Watch Time",92 width: 130,93 type: "number",94 aggregation: { type: "average" },95 valueFormatter: ({ value }) => (typeof value === "number" ? `${Math.round(value)}min` : ""),96 },97 { accessor: "status", label: "Status", width: 120, type: "string" },98];99100export const aggregateFunctionsData = [101 {102 id: 1,103 name: "StreamFlix",104 status: "Leading Platform",105 categories: [106 {107 id: 101,108 name: "Gaming",109 status: "Trending",110 creators: [111 { id: 1001, name: "PixelMaster", followers: 2800000, revenue: "$45.2K", rating: 4.8, contentCount: 328, avgViewTime: 45, status: "Partner" },112 { id: 1002, name: "RetroGamer93", followers: 1200000, revenue: "$28.5K", rating: 4.6, contentCount: 156, avgViewTime: 52, status: "Partner" },113 { id: 1003, name: "SpeedrunQueen", followers: 890000, revenue: "$22.1K", rating: 4.9, contentCount: 89, avgViewTime: 38, status: "Partner" },114 ],115 },116 {117 id: 102,118 name: "Music & Arts",119 status: "Growing",120 creators: [121 { id: 1101, name: "MelodyMaker", followers: 1650000, revenue: "$31.8K", rating: 4.7, contentCount: 203, avgViewTime: 28, status: "Partner" },122 { id: 1102, name: "DigitalArtist", followers: 720000, revenue: "$18.9K", rating: 4.5, contentCount: 127, avgViewTime: 35, status: "Affiliate" },123 { id: 1103, name: "JazzVibez", followers: 430000, revenue: "$12.4K", rating: 4.8, contentCount: 78, avgViewTime: 42, status: "Affiliate" },124 ],125 },126 {127 id: 103,128 name: "Cooking & Lifestyle",129 status: "Stable",130 creators: [131 { id: 1201, name: "ChefExtraordinaire", followers: 3200000, revenue: "$58.7K", rating: 4.9, contentCount: 245, avgViewTime: 22, status: "Partner" },132 { id: 1202, name: "HomeDecorGuru", followers: 980000, revenue: "$19.3K", rating: 4.4, contentCount: 134, avgViewTime: 18, status: "Affiliate" },133 ],134 },135 ],136 },137 {138 id: 2,139 name: "WatchNow",140 status: "Competitor",141 categories: [142 {143 id: 201,144 name: "Tech Reviews",145 status: "Hot",146 creators: [147 { id: 2001, name: "TechGuru2024", followers: 2100000, revenue: "$42.6K", rating: 4.6, contentCount: 189, avgViewTime: 35, status: "Partner" },148 { id: 2002, name: "GadgetWhisperer", followers: 1450000, revenue: "$29.1K", rating: 4.7, contentCount: 156, avgViewTime: 31, status: "Partner" },149 { id: 2003, name: "CodeReviewer", followers: 680000, revenue: "$16.8K", rating: 4.8, contentCount: 94, avgViewTime: 48, status: "Affiliate" },150 ],151 },152 {153 id: 202,154 name: "Fitness & Health",155 status: "Growing",156 creators: [157 { id: 2101, name: "FitnessPhenom", followers: 1890000, revenue: "$35.4K", rating: 4.5, contentCount: 312, avgViewTime: 25, status: "Partner" },158 { id: 2102, name: "YogaMaster", followers: 1100000, revenue: "$21.7K", rating: 4.9, contentCount: 178, avgViewTime: 33, status: "Partner" },159 ],160 },161 ],162 },163 {164 id: 3,165 name: "CreativeSpace",166 status: "Emerging",167 categories: [168 {169 id: 301,170 name: "Photography",171 status: "Niche",172 creators: [173 { id: 3001, name: "LensArtist", followers: 750000, revenue: "$18.2K", rating: 4.7, contentCount: 145, avgViewTime: 27, status: "Partner" },174 { id: 3002, name: "NatureShooter", followers: 520000, revenue: "$13.5K", rating: 4.6, contentCount: 98, avgViewTime: 29, status: "Affiliate" },175 { id: 3003, name: "PortraitPro", followers: 390000, revenue: "$9.8K", rating: 4.8, contentCount: 67, avgViewTime: 24, status: "Affiliate" },176 ],177 },178 {179 id: 302,180 name: "Animation & VFX",181 status: "Specialized",182 creators: [183 { id: 3101, name: "3DAnimator", followers: 640000, revenue: "$15.9K", rating: 4.9, contentCount: 58, avgViewTime: 41, status: "Partner" },184 { id: 3102, name: "VFXWizard", followers: 480000, revenue: "$12.3K", rating: 4.7, contentCount: 42, avgViewTime: 38, status: "Affiliate" },185 ],186 },187 ],188 },189 {190 id: 4,191 name: "EduStream",192 status: "Educational Focus",193 categories: [194 {195 id: 401,196 name: "Science & Math",197 status: "Educational",198 creators: [199 { id: 4001, name: "MathExplainer", followers: 1340000, revenue: "$26.8K", rating: 4.8, contentCount: 234, avgViewTime: 36, status: "Partner" },200 { id: 4002, name: "PhysicsPhun", followers: 890000, revenue: "$19.4K", rating: 4.6, contentCount: 167, avgViewTime: 42, status: "Partner" },201 { id: 4003, name: "ChemistryLab", followers: 560000, revenue: "$14.2K", rating: 4.7, contentCount: 89, avgViewTime: 33, status: "Affiliate" },202 ],203 },204 {205 id: 402,206 name: "History & Culture",207 status: "Informative",208 creators: [209 { id: 4101, name: "HistoryBuff", followers: 920000, revenue: "$18.6K", rating: 4.5, contentCount: 145, avgViewTime: 39, status: "Partner" },210 { id: 4102, name: "CultureExplorer", followers: 670000, revenue: "$15.1K", rating: 4.8, contentCount: 112, avgViewTime: 45, status: "Affiliate" },211 ],212 },213 ],214 },215];216217export const aggregateFunctionsConfig = {218 headers: aggregateFunctionsHeaders,219 rows: aggregateFunctionsData,220 tableProps: {221 rowGrouping: ["categories", "creators"] as string[],222 columnResizing: true,223 },224} as const;225
Svelte
Copy
1<script lang="ts">2 import {SimpleTable} from "@simple-table/svelte"; import type { Theme } from "@simple-table/svelte";3 import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";4 import "@simple-table/svelte/styles.css";56 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();7</script>89<SimpleTable10 columns={aggregateFunctionsConfig.headers}11 rows={aggregateFunctionsConfig.rows}12 rowGrouping={aggregateFunctionsConfig.tableProps.rowGrouping}13 columnResizing={true}14 {height}15 {theme}16/>
Solid TSX
Copy
1import {SimpleTable} from "@simple-table/solid";import type { Theme } from "@simple-table/solid";2import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";3import "@simple-table/solid/styles.css";45export default function AggregateFunctionsDemo(props: {6 height?: string | number;7 theme?: Theme;8}) {9 return (10 <SimpleTable11 columns={aggregateFunctionsConfig.headers}12 rows={aggregateFunctionsConfig.rows}13 rowGrouping={aggregateFunctionsConfig.tableProps.rowGrouping}14 columnResizing15 height={props.height ?? "400px"}16 theme={props.theme}17 />18 );19}
TypeScriptAggregateFunctionsDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { Theme } from "simple-table-core";3import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";4import "simple-table-core/styles.css";56export function renderAggregateFunctionsDemo(7 container: HTMLElement,8 options?: { height?: string | number; theme?: Theme }9): SimpleTableVanilla {10 const table = new SimpleTableVanilla(container, {11 columns: aggregateFunctionsConfig.headers,12 rows: aggregateFunctionsConfig.rows,13 rowGrouping: aggregateFunctionsConfig.tableProps.rowGrouping,14 columnResizing: true,15 height: options?.height ?? "400px",16 theme: options?.theme,17 });18 return table;19}202122// aggregate-functions.demo-data.ts23// Self-contained demo table setup for this example.24import type { ColumnDef } from "simple-table-core";252627export const aggregateFunctionsHeaders: ColumnDef[] = [28 { accessor: "name", label: "Name", width: 200, expandable: true, type: "string" },29 {30 accessor: "followers",31 label: "Followers",32 width: 120,33 type: "number",34 aggregation: { type: "sum" },35 valueFormatter: ({ value }) => {36 if (typeof value === "number") {37 return value >= 100000038 ? `${(value / 1000000).toFixed(1)}M`39 : value >= 100040 ? `${(value / 1000).toFixed(0)}K`41 : value.toString();42 }43 return "";44 },45 },46 {47 accessor: "revenue",48 label: "Monthly Revenue",49 width: 140,50 type: "string",51 aggregation: {52 type: "sum",53 parseValue: (value) => {54 if (typeof value !== "string") return 0;55 const numericValue = parseFloat(value.replace(/[$K]/g, ""));56 return isNaN(numericValue) ? 0 : numericValue;57 },58 },59 valueFormatter: ({ value }) => {60 if (typeof value === "number") return `$${value.toFixed(1)}K`;61 if (typeof value === "string") return value;62 return "";63 },64 },65 {66 accessor: "rating",67 label: "Rating",68 width: 100,69 type: "number",70 aggregation: { type: "average" },71 valueFormatter: ({ value }) => (typeof value === "number" ? `${value.toFixed(1)} ⭐` : ""),72 },73 {74 accessor: "contentCount",75 label: "Content",76 width: 90,77 type: "number",78 aggregation: { type: "sum" },79 },80 {81 accessor: "avgViewTime",82 label: "Avg Watch Time",83 width: 130,84 type: "number",85 aggregation: { type: "average" },86 valueFormatter: ({ value }) => (typeof value === "number" ? `${Math.round(value)}min` : ""),87 },88 { accessor: "status", label: "Status", width: 120, type: "string" },89];9091export const aggregateFunctionsData = [92 {93 id: 1,94 name: "StreamFlix",95 status: "Leading Platform",96 categories: [97 {98 id: 101,99 name: "Gaming",100 status: "Trending",101 creators: [102 { id: 1001, name: "PixelMaster", followers: 2800000, revenue: "$45.2K", rating: 4.8, contentCount: 328, avgViewTime: 45, status: "Partner" },103 { id: 1002, name: "RetroGamer93", followers: 1200000, revenue: "$28.5K", rating: 4.6, contentCount: 156, avgViewTime: 52, status: "Partner" },104 { id: 1003, name: "SpeedrunQueen", followers: 890000, revenue: "$22.1K", rating: 4.9, contentCount: 89, avgViewTime: 38, status: "Partner" },105 ],106 },107 {108 id: 102,109 name: "Music & Arts",110 status: "Growing",111 creators: [112 { id: 1101, name: "MelodyMaker", followers: 1650000, revenue: "$31.8K", rating: 4.7, contentCount: 203, avgViewTime: 28, status: "Partner" },113 { id: 1102, name: "DigitalArtist", followers: 720000, revenue: "$18.9K", rating: 4.5, contentCount: 127, avgViewTime: 35, status: "Affiliate" },114 { id: 1103, name: "JazzVibez", followers: 430000, revenue: "$12.4K", rating: 4.8, contentCount: 78, avgViewTime: 42, status: "Affiliate" },115 ],116 },117 {118 id: 103,119 name: "Cooking & Lifestyle",120 status: "Stable",121 creators: [122 { id: 1201, name: "ChefExtraordinaire", followers: 3200000, revenue: "$58.7K", rating: 4.9, contentCount: 245, avgViewTime: 22, status: "Partner" },123 { id: 1202, name: "HomeDecorGuru", followers: 980000, revenue: "$19.3K", rating: 4.4, contentCount: 134, avgViewTime: 18, status: "Affiliate" },124 ],125 },126 ],127 },128 {129 id: 2,130 name: "WatchNow",131 status: "Competitor",132 categories: [133 {134 id: 201,135 name: "Tech Reviews",136 status: "Hot",137 creators: [138 { id: 2001, name: "TechGuru2024", followers: 2100000, revenue: "$42.6K", rating: 4.6, contentCount: 189, avgViewTime: 35, status: "Partner" },139 { id: 2002, name: "GadgetWhisperer", followers: 1450000, revenue: "$29.1K", rating: 4.7, contentCount: 156, avgViewTime: 31, status: "Partner" },140 { id: 2003, name: "CodeReviewer", followers: 680000, revenue: "$16.8K", rating: 4.8, contentCount: 94, avgViewTime: 48, status: "Affiliate" },141 ],142 },143 {144 id: 202,145 name: "Fitness & Health",146 status: "Growing",147 creators: [148 { id: 2101, name: "FitnessPhenom", followers: 1890000, revenue: "$35.4K", rating: 4.5, contentCount: 312, avgViewTime: 25, status: "Partner" },149 { id: 2102, name: "YogaMaster", followers: 1100000, revenue: "$21.7K", rating: 4.9, contentCount: 178, avgViewTime: 33, status: "Partner" },150 ],151 },152 ],153 },154 {155 id: 3,156 name: "CreativeSpace",157 status: "Emerging",158 categories: [159 {160 id: 301,161 name: "Photography",162 status: "Niche",163 creators: [164 { id: 3001, name: "LensArtist", followers: 750000, revenue: "$18.2K", rating: 4.7, contentCount: 145, avgViewTime: 27, status: "Partner" },165 { id: 3002, name: "NatureShooter", followers: 520000, revenue: "$13.5K", rating: 4.6, contentCount: 98, avgViewTime: 29, status: "Affiliate" },166 { id: 3003, name: "PortraitPro", followers: 390000, revenue: "$9.8K", rating: 4.8, contentCount: 67, avgViewTime: 24, status: "Affiliate" },167 ],168 },169 {170 id: 302,171 name: "Animation & VFX",172 status: "Specialized",173 creators: [174 { id: 3101, name: "3DAnimator", followers: 640000, revenue: "$15.9K", rating: 4.9, contentCount: 58, avgViewTime: 41, status: "Partner" },175 { id: 3102, name: "VFXWizard", followers: 480000, revenue: "$12.3K", rating: 4.7, contentCount: 42, avgViewTime: 38, status: "Affiliate" },176 ],177 },178 ],179 },180 {181 id: 4,182 name: "EduStream",183 status: "Educational Focus",184 categories: [185 {186 id: 401,187 name: "Science & Math",188 status: "Educational",189 creators: [190 { id: 4001, name: "MathExplainer", followers: 1340000, revenue: "$26.8K", rating: 4.8, contentCount: 234, avgViewTime: 36, status: "Partner" },191 { id: 4002, name: "PhysicsPhun", followers: 890000, revenue: "$19.4K", rating: 4.6, contentCount: 167, avgViewTime: 42, status: "Partner" },192 { id: 4003, name: "ChemistryLab", followers: 560000, revenue: "$14.2K", rating: 4.7, contentCount: 89, avgViewTime: 33, status: "Affiliate" },193 ],194 },195 {196 id: 402,197 name: "History & Culture",198 status: "Informative",199 creators: [200 { id: 4101, name: "HistoryBuff", followers: 920000, revenue: "$18.6K", rating: 4.5, contentCount: 145, avgViewTime: 39, status: "Partner" },201 { id: 4102, name: "CultureExplorer", followers: 670000, revenue: "$15.1K", rating: 4.8, contentCount: 112, avgViewTime: 45, status: "Affiliate" },202 ],203 },204 ],205 },206];207208export const aggregateFunctionsConfig = {209 headers: aggregateFunctionsHeaders,210 rows: aggregateFunctionsData,211 tableProps: {212 rowGrouping: ["categories", "creators"] as string[],213 columnResizing: true,214 },215} as const;216
Props
Aggregation Configuration
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
ColumnDef.aggregation | Optional | Aggregates child values into parent group rows. Requires rowGrouping. Built-ins: sum, average, count, min, max, or custom. |
AggregationConfig
| Property | Required | Description | Example |
|---|---|---|---|
Property | Required | Description | Example |
type | Required | The aggregation function to use | |
parseValue(value: any) => number | Optional | Function to parse string values to numbers (e.g., '$15.0M' to 15000000) | |
formatResult(value: number) => string | Optional | Function to format the aggregated result back to string | |
customFn(values: any[]) => any | Optional | Custom aggregation function (only when type is 'custom') |