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";2import type { Theme } from "@simple-table/react";3import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";4import "@simple-table/react/styles.css";56const AggregateFunctionsDemo = ({7 height = "400px",8 theme,9}: {10 height?: string | number;11 theme?: Theme;12}) => {13 return (14 <SimpleTable15 columns={aggregateFunctionsConfig.headers}16 getRowId={({ row }) => row.id}17 rows={aggregateFunctionsConfig.rows}18 rowGrouping={aggregateFunctionsConfig.tableProps.rowGrouping}19 columnResizing20 height={height}21 theme={theme}22 />23 );24};2526export default AggregateFunctionsDemo;
Angularaggregate-functions-demo.component.ts
Copy
1import { Component, Input } from "@angular/core";2import {SimpleTableComponent} from "@simple-table/angular";import type { AngularColumnDef, GetRowIdParams, Theme } from "@simple-table/angular";3import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";4import "@simple-table/angular/styles.css";5import type { AggregateFunctionsRow } from "./aggregate-functions.demo-data";67@Component({8 selector: "aggregate-functions-demo",9 standalone: true,10 imports: [SimpleTableComponent],11 template: `12 <simple-table13 [getRowId]="getRowId"14 [rows]="rows"15 [columns]="headers"16 [rowGrouping]="grouping"17 [columnResizing]="true"18 [height]="height"19 [theme]="theme"20 ></simple-table>21 `,22})23export class AggregateFunctionsDemoComponent {24 @Input() height: string | number = "400px";25 @Input() theme?: Theme;2627 readonly rows: AggregateFunctionsRow[] = aggregateFunctionsConfig.rows;28 readonly headers: AngularColumnDef<AggregateFunctionsRow>[] = aggregateFunctionsConfig.headers;29 readonly grouping = aggregateFunctionsConfig.tableProps.rowGrouping;3031 getRowId = ({ row }: GetRowIdParams<AggregateFunctionsRow>) => row.id;32}333435// aggregate-functions.demo-data.ts36// Self-contained demo table setup for this example.37import type { AngularColumnDef, ValueFormatterProps } from "@simple-table/angular";3839/** Platform → category → creator nesting used by rowGrouping. */40export type AggregateFunctionsRow = {41 id: number;42 name: string;43 status: string;44 followers?: number;45 revenue?: string;46 rating?: number;47 contentCount?: number;48 avgViewTime?: number;49 categories?: AggregateFunctionsRow[];50 creators?: AggregateFunctionsRow[];51};5253export const aggregateFunctionsHeaders: AngularColumnDef<AggregateFunctionsRow>[] = [54 { accessor: "name", label: "Name", width: 200, expandable: true, type: "string" },55 {56 accessor: "followers",57 label: "Followers",58 width: 120,59 type: "number",60 aggregation: { type: "sum" },61 valueFormatter: ({ value }: ValueFormatterProps<AggregateFunctionsRow>) => {62 if (typeof value === "number") {63 return value >= 100000064 ? `${(value / 1000000).toFixed(1)}M`65 : value >= 100066 ? `${(value / 1000).toFixed(0)}K`67 : value.toString();68 }69 return "";70 },71 },72 {73 accessor: "revenue",74 label: "Monthly Revenue",75 width: 140,76 type: "string",77 aggregation: {78 type: "sum",79 parseValue: (value) => {80 if (typeof value !== "string") return 0;81 const numericValue = parseFloat(value.replace(/[$K]/g, ""));82 return isNaN(numericValue) ? 0 : numericValue;83 },84 },85 valueFormatter: ({ value }: ValueFormatterProps<AggregateFunctionsRow>) => {86 if (typeof value === "number") return `$${value.toFixed(1)}K`;87 if (typeof value === "string") return value;88 return "";89 },90 },91 {92 accessor: "rating",93 label: "Rating",94 width: 100,95 type: "number",96 aggregation: { type: "average" },97 valueFormatter: ({ value }: ValueFormatterProps<AggregateFunctionsRow>) => (typeof value === "number" ? `${value.toFixed(1)} ⭐` : ""),98 },99 {100 accessor: "contentCount",101 label: "Content",102 width: 90,103 type: "number",104 aggregation: { type: "sum" },105 },106 {107 accessor: "avgViewTime",108 label: "Avg Watch Time",109 width: 130,110 type: "number",111 aggregation: { type: "average" },112 valueFormatter: ({ value }: ValueFormatterProps<AggregateFunctionsRow>) => (typeof value === "number" ? `${Math.round(value)}min` : ""),113 },114 { accessor: "status", label: "Status", width: 120, type: "string" },115];116117export const aggregateFunctionsData: AggregateFunctionsRow[] = [118 {119 id: 1,120 name: "StreamFlix",121 status: "Leading Platform",122 categories: [123 {124 id: 101,125 name: "Gaming",126 status: "Trending",127 creators: [128 { id: 1001, name: "PixelMaster", followers: 2800000, revenue: "$45.2K", rating: 4.8, contentCount: 328, avgViewTime: 45, status: "Partner" },129 { id: 1002, name: "RetroGamer93", followers: 1200000, revenue: "$28.5K", rating: 4.6, contentCount: 156, avgViewTime: 52, status: "Partner" },130 { id: 1003, name: "SpeedrunQueen", followers: 890000, revenue: "$22.1K", rating: 4.9, contentCount: 89, avgViewTime: 38, status: "Partner" },131 ],132 },133 {134 id: 102,135 name: "Music & Arts",136 status: "Growing",137 creators: [138 { id: 1101, name: "MelodyMaker", followers: 1650000, revenue: "$31.8K", rating: 4.7, contentCount: 203, avgViewTime: 28, status: "Partner" },139 { id: 1102, name: "DigitalArtist", followers: 720000, revenue: "$18.9K", rating: 4.5, contentCount: 127, avgViewTime: 35, status: "Affiliate" },140 { id: 1103, name: "JazzVibez", followers: 430000, revenue: "$12.4K", rating: 4.8, contentCount: 78, avgViewTime: 42, status: "Affiliate" },141 ],142 },143 {144 id: 103,145 name: "Cooking & Lifestyle",146 status: "Stable",147 creators: [148 { id: 1201, name: "ChefExtraordinaire", followers: 3200000, revenue: "$58.7K", rating: 4.9, contentCount: 245, avgViewTime: 22, status: "Partner" },149 { id: 1202, name: "HomeDecorGuru", followers: 980000, revenue: "$19.3K", rating: 4.4, contentCount: 134, avgViewTime: 18, status: "Affiliate" },150 ],151 },152 ],153 },154 {155 id: 2,156 name: "WatchNow",157 status: "Competitor",158 categories: [159 {160 id: 201,161 name: "Tech Reviews",162 status: "Hot",163 creators: [164 { id: 2001, name: "TechGuru2024", followers: 2100000, revenue: "$42.6K", rating: 4.6, contentCount: 189, avgViewTime: 35, status: "Partner" },165 { id: 2002, name: "GadgetWhisperer", followers: 1450000, revenue: "$29.1K", rating: 4.7, contentCount: 156, avgViewTime: 31, status: "Partner" },166 { id: 2003, name: "CodeReviewer", followers: 680000, revenue: "$16.8K", rating: 4.8, contentCount: 94, avgViewTime: 48, status: "Affiliate" },167 ],168 },169 {170 id: 202,171 name: "Fitness & Health",172 status: "Growing",173 creators: [174 { id: 2101, name: "FitnessPhenom", followers: 1890000, revenue: "$35.4K", rating: 4.5, contentCount: 312, avgViewTime: 25, status: "Partner" },175 { id: 2102, name: "YogaMaster", followers: 1100000, revenue: "$21.7K", rating: 4.9, contentCount: 178, avgViewTime: 33, status: "Partner" },176 ],177 },178 ],179 },180 {181 id: 3,182 name: "CreativeSpace",183 status: "Emerging",184 categories: [185 {186 id: 301,187 name: "Photography",188 status: "Niche",189 creators: [190 { id: 3001, name: "LensArtist", followers: 750000, revenue: "$18.2K", rating: 4.7, contentCount: 145, avgViewTime: 27, status: "Partner" },191 { id: 3002, name: "NatureShooter", followers: 520000, revenue: "$13.5K", rating: 4.6, contentCount: 98, avgViewTime: 29, status: "Affiliate" },192 { id: 3003, name: "PortraitPro", followers: 390000, revenue: "$9.8K", rating: 4.8, contentCount: 67, avgViewTime: 24, status: "Affiliate" },193 ],194 },195 {196 id: 302,197 name: "Animation & VFX",198 status: "Specialized",199 creators: [200 { id: 3101, name: "3DAnimator", followers: 640000, revenue: "$15.9K", rating: 4.9, contentCount: 58, avgViewTime: 41, status: "Partner" },201 { id: 3102, name: "VFXWizard", followers: 480000, revenue: "$12.3K", rating: 4.7, contentCount: 42, avgViewTime: 38, status: "Affiliate" },202 ],203 },204 ],205 },206 {207 id: 4,208 name: "EduStream",209 status: "Educational Focus",210 categories: [211 {212 id: 401,213 name: "Science & Math",214 status: "Educational",215 creators: [216 { id: 4001, name: "MathExplainer", followers: 1340000, revenue: "$26.8K", rating: 4.8, contentCount: 234, avgViewTime: 36, status: "Partner" },217 { id: 4002, name: "PhysicsPhun", followers: 890000, revenue: "$19.4K", rating: 4.6, contentCount: 167, avgViewTime: 42, status: "Partner" },218 { id: 4003, name: "ChemistryLab", followers: 560000, revenue: "$14.2K", rating: 4.7, contentCount: 89, avgViewTime: 33, status: "Affiliate" },219 ],220 },221 {222 id: 402,223 name: "History & Culture",224 status: "Informative",225 creators: [226 { id: 4101, name: "HistoryBuff", followers: 920000, revenue: "$18.6K", rating: 4.5, contentCount: 145, avgViewTime: 39, status: "Partner" },227 { id: 4102, name: "CultureExplorer", followers: 670000, revenue: "$15.1K", rating: 4.8, contentCount: 112, avgViewTime: 45, status: "Affiliate" },228 ],229 },230 ],231 },232];233234export const aggregateFunctionsConfig = {235 headers: aggregateFunctionsHeaders,236 rows: aggregateFunctionsData,237 tableProps: {238 rowGrouping: ["categories", "creators"],239 columnResizing: true,240 },241};242
Vue SFC
Copy
1<template>2 <SimpleTable3 :columns="aggregateFunctionsConfig.headers"4 :rows="aggregateFunctionsConfig.rows"5 :get-row-id="getRowId"6 :row-grouping="aggregateFunctionsConfig.tableProps.rowGrouping"7 :column-resizing="true"8 :height="height"9 :theme="theme"10 />11</template>1213<script setup lang="ts">14import { SimpleTable } from "@simple-table/vue";15import type { Theme, GetRowIdParams } from "@simple-table/vue";16import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";17import type { AggregateFunctionsRow } from "./aggregate-functions.demo-data";18import "@simple-table/vue/styles.css";1920withDefaults(defineProps<{ height?: string | number; theme?: Theme }>(), {21 height: "400px",22});2324const getRowId = ({ row }: GetRowIdParams<AggregateFunctionsRow>) => row.id;25</script>
Svelte
Copy
1<script lang="ts">2 import { SimpleTable } from "@simple-table/svelte";3 import type { Theme, GetRowIdParams } from "@simple-table/svelte";4 import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";5 import type { AggregateFunctionsRow } from "./aggregate-functions.demo-data";6 import "@simple-table/svelte/styles.css";78 let { height = "400px", theme }: { height?: string | number; theme?: Theme } = $props();910 const getRowId = ({ row }: GetRowIdParams<AggregateFunctionsRow>) => row.id;11</script>1213<SimpleTable14 columns={aggregateFunctionsConfig.headers}15 rows={aggregateFunctionsConfig.rows}16 getRowId={getRowId}17 rowGrouping={aggregateFunctionsConfig.tableProps.rowGrouping}18 columnResizing={true}19 {height}20 {theme}21/>
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 getRowId={({ row }) => row.id}13 rows={aggregateFunctionsConfig.rows}14 rowGrouping={aggregateFunctionsConfig.tableProps.rowGrouping}15 columnResizing16 height={props.height ?? "400px"}17 theme={props.theme}18 />19 );20}
TypeScriptAggregateFunctionsDemo.ts
Copy
1import { SimpleTableVanilla } from "simple-table-core";2import type { AggregateFunctionsRow } from "./aggregate-functions.demo-data";3import type { Theme, GetRowIdParams } from "simple-table-core";4import { aggregateFunctionsConfig } from "./aggregate-functions.demo-data";5import "simple-table-core/styles.css";678const getRowId = ({ row }: GetRowIdParams<AggregateFunctionsRow>) => row.id;9export function renderAggregateFunctionsDemo(10 container: HTMLElement,11 options?: { height?: string | number; theme?: Theme }12): SimpleTableVanilla<AggregateFunctionsRow> {13 const table = new SimpleTableVanilla(container, {14 getRowId,15 columns: aggregateFunctionsConfig.headers,16 rows: aggregateFunctionsConfig.rows,17 rowGrouping: aggregateFunctionsConfig.tableProps.rowGrouping,18 columnResizing: true,19 height: options?.height ?? "400px",20 theme: options?.theme,21 });22 return table;23}242526// aggregate-functions.demo-data.ts27// Self-contained demo table setup for this example.28import type { ColumnDef } from "simple-table-core";2930/** Platform → category → creator nesting used by rowGrouping. */31export type AggregateFunctionsRow = {32 id: number;33 name: string;34 status: string;35 followers?: number;36 revenue?: string;37 rating?: number;38 contentCount?: number;39 avgViewTime?: number;40 categories?: AggregateFunctionsRow[];41 creators?: AggregateFunctionsRow[];42};4344export const aggregateFunctionsHeaders: ColumnDef<AggregateFunctionsRow>[] = [45 { accessor: "name", label: "Name", width: 200, expandable: true, type: "string" },46 {47 accessor: "followers",48 label: "Followers",49 width: 120,50 type: "number",51 aggregation: { type: "sum" },52 valueFormatter: ({ value }) => {53 if (typeof value === "number") {54 return value >= 100000055 ? `${(value / 1000000).toFixed(1)}M`56 : value >= 100057 ? `${(value / 1000).toFixed(0)}K`58 : value.toString();59 }60 return "";61 },62 },63 {64 accessor: "revenue",65 label: "Monthly Revenue",66 width: 140,67 type: "string",68 aggregation: {69 type: "sum",70 parseValue: (value) => {71 if (typeof value !== "string") return 0;72 const numericValue = parseFloat(value.replace(/[$K]/g, ""));73 return isNaN(numericValue) ? 0 : numericValue;74 },75 },76 valueFormatter: ({ value }) => {77 if (typeof value === "number") return `$${value.toFixed(1)}K`;78 if (typeof value === "string") return value;79 return "";80 },81 },82 {83 accessor: "rating",84 label: "Rating",85 width: 100,86 type: "number",87 aggregation: { type: "average" },88 valueFormatter: ({ value }) => (typeof value === "number" ? `${value.toFixed(1)} ⭐` : ""),89 },90 {91 accessor: "contentCount",92 label: "Content",93 width: 90,94 type: "number",95 aggregation: { type: "sum" },96 },97 {98 accessor: "avgViewTime",99 label: "Avg Watch Time",100 width: 130,101 type: "number",102 aggregation: { type: "average" },103 valueFormatter: ({ value }) => (typeof value === "number" ? `${Math.round(value)}min` : ""),104 },105 { accessor: "status", label: "Status", width: 120, type: "string" },106];107108export const aggregateFunctionsData: AggregateFunctionsRow[] = [109 {110 id: 1,111 name: "StreamFlix",112 status: "Leading Platform",113 categories: [114 {115 id: 101,116 name: "Gaming",117 status: "Trending",118 creators: [119 { id: 1001, name: "PixelMaster", followers: 2800000, revenue: "$45.2K", rating: 4.8, contentCount: 328, avgViewTime: 45, status: "Partner" },120 { id: 1002, name: "RetroGamer93", followers: 1200000, revenue: "$28.5K", rating: 4.6, contentCount: 156, avgViewTime: 52, status: "Partner" },121 { id: 1003, name: "SpeedrunQueen", followers: 890000, revenue: "$22.1K", rating: 4.9, contentCount: 89, avgViewTime: 38, status: "Partner" },122 ],123 },124 {125 id: 102,126 name: "Music & Arts",127 status: "Growing",128 creators: [129 { id: 1101, name: "MelodyMaker", followers: 1650000, revenue: "$31.8K", rating: 4.7, contentCount: 203, avgViewTime: 28, status: "Partner" },130 { id: 1102, name: "DigitalArtist", followers: 720000, revenue: "$18.9K", rating: 4.5, contentCount: 127, avgViewTime: 35, status: "Affiliate" },131 { id: 1103, name: "JazzVibez", followers: 430000, revenue: "$12.4K", rating: 4.8, contentCount: 78, avgViewTime: 42, status: "Affiliate" },132 ],133 },134 {135 id: 103,136 name: "Cooking & Lifestyle",137 status: "Stable",138 creators: [139 { id: 1201, name: "ChefExtraordinaire", followers: 3200000, revenue: "$58.7K", rating: 4.9, contentCount: 245, avgViewTime: 22, status: "Partner" },140 { id: 1202, name: "HomeDecorGuru", followers: 980000, revenue: "$19.3K", rating: 4.4, contentCount: 134, avgViewTime: 18, status: "Affiliate" },141 ],142 },143 ],144 },145 {146 id: 2,147 name: "WatchNow",148 status: "Competitor",149 categories: [150 {151 id: 201,152 name: "Tech Reviews",153 status: "Hot",154 creators: [155 { id: 2001, name: "TechGuru2024", followers: 2100000, revenue: "$42.6K", rating: 4.6, contentCount: 189, avgViewTime: 35, status: "Partner" },156 { id: 2002, name: "GadgetWhisperer", followers: 1450000, revenue: "$29.1K", rating: 4.7, contentCount: 156, avgViewTime: 31, status: "Partner" },157 { id: 2003, name: "CodeReviewer", followers: 680000, revenue: "$16.8K", rating: 4.8, contentCount: 94, avgViewTime: 48, status: "Affiliate" },158 ],159 },160 {161 id: 202,162 name: "Fitness & Health",163 status: "Growing",164 creators: [165 { id: 2101, name: "FitnessPhenom", followers: 1890000, revenue: "$35.4K", rating: 4.5, contentCount: 312, avgViewTime: 25, status: "Partner" },166 { id: 2102, name: "YogaMaster", followers: 1100000, revenue: "$21.7K", rating: 4.9, contentCount: 178, avgViewTime: 33, status: "Partner" },167 ],168 },169 ],170 },171 {172 id: 3,173 name: "CreativeSpace",174 status: "Emerging",175 categories: [176 {177 id: 301,178 name: "Photography",179 status: "Niche",180 creators: [181 { id: 3001, name: "LensArtist", followers: 750000, revenue: "$18.2K", rating: 4.7, contentCount: 145, avgViewTime: 27, status: "Partner" },182 { id: 3002, name: "NatureShooter", followers: 520000, revenue: "$13.5K", rating: 4.6, contentCount: 98, avgViewTime: 29, status: "Affiliate" },183 { id: 3003, name: "PortraitPro", followers: 390000, revenue: "$9.8K", rating: 4.8, contentCount: 67, avgViewTime: 24, status: "Affiliate" },184 ],185 },186 {187 id: 302,188 name: "Animation & VFX",189 status: "Specialized",190 creators: [191 { id: 3101, name: "3DAnimator", followers: 640000, revenue: "$15.9K", rating: 4.9, contentCount: 58, avgViewTime: 41, status: "Partner" },192 { id: 3102, name: "VFXWizard", followers: 480000, revenue: "$12.3K", rating: 4.7, contentCount: 42, avgViewTime: 38, status: "Affiliate" },193 ],194 },195 ],196 },197 {198 id: 4,199 name: "EduStream",200 status: "Educational Focus",201 categories: [202 {203 id: 401,204 name: "Science & Math",205 status: "Educational",206 creators: [207 { id: 4001, name: "MathExplainer", followers: 1340000, revenue: "$26.8K", rating: 4.8, contentCount: 234, avgViewTime: 36, status: "Partner" },208 { id: 4002, name: "PhysicsPhun", followers: 890000, revenue: "$19.4K", rating: 4.6, contentCount: 167, avgViewTime: 42, status: "Partner" },209 { id: 4003, name: "ChemistryLab", followers: 560000, revenue: "$14.2K", rating: 4.7, contentCount: 89, avgViewTime: 33, status: "Affiliate" },210 ],211 },212 {213 id: 402,214 name: "History & Culture",215 status: "Informative",216 creators: [217 { id: 4101, name: "HistoryBuff", followers: 920000, revenue: "$18.6K", rating: 4.5, contentCount: 145, avgViewTime: 39, status: "Partner" },218 { id: 4102, name: "CultureExplorer", followers: 670000, revenue: "$15.1K", rating: 4.8, contentCount: 112, avgViewTime: 45, status: "Affiliate" },219 ],220 },221 ],222 },223];224225export const aggregateFunctionsConfig = {226 headers: aggregateFunctionsHeaders,227 rows: aggregateFunctionsData,228 tableProps: {229 rowGrouping: ["categories", "creators"],230 columnResizing: true,231 },232};233
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') |