This section covers how custom aggregation functions can be supplied and used in the grid.
Custom aggregation functions can be supplied directly to colDef.aggFunc
as shown below:
const [columnDefs, setColumnDefs] = useState([
{
field: 'total',
aggFunc: params => {
let total = 0;
params.values.forEach(value => total += value);
return total;
}
}
]);
<AgGridReact columnDefs={columnDefs} />
As shown above, a custom agg function is supplied directly to the aggFunc
property. The custom function uses the
provided values
to perform the custom aggregation. See Aggregation API Reference to
learn more about the supplied params
.
This is the simplest way to supply custom functions, however it has limitations compared with Registering Custom Functions.
Direct Functions will not appear in the Columns Tool Panel or work when Saving and Applying Column State.
The example below uses the direct aggFunc
approach shown in the above snippet. Note the following:
rowGroup
column definition property.func(Total)
is displayed in the column header by default as it's a direct function.agg(Total)
appears in the Columns Tool Panel, but it's omitted from the drop-down list as it's not registered with the grid.Custom functions that are registered with the grid can be referenced by name in column definitions and will
appear in the Columns Tool Panel just like any Built-In Function,
and is done using the aggFuncs
grid option:
The following snippet shows how to register custom functions using the aggFuncs
grid option:
const [columnDefs, setColumnDefs] = useState([
{ field: 'sales', aggFunc: 'mySum' },
]);
const [aggFuncs, setAggFuncs] = useMemo(() => {
return {
'mySum': params => {
let sum = 0;
params.values.forEach(value => sum += value);
return sum;
}
};
}, []);
<AgGridReact
columnDefs={columnDefs}
aggFuncs={aggFuncs}
/>
As shown above, a custom function is registered with in the grid with the name 'mySum' and is referenced by name in
the column definition using the aggFunc
property.
Note that custom aggregation functions can also be registered using gridApi.addAggFunc('mySum', mySumFunc)
.
The example below uses the aggFuncs
approach shown in the snippet above. Note the following:
rowGroup
column definition property.mySum(Total)
is displayed in the column header by default as it uses the registered function name.mySum(Total)
appears in the Columns Tool Panel and appears in the drop-down list just like a built-in function.It is possible to add your own custom aggregation to the grid. Custom aggregation functions can be applied directly to the column or registered to the grid and reference by name (similar to grid provided functions).
A custom aggregation function takes values to aggregate and aggregates them.
Javascript doesn't always represent decimal numbers correctly (e.g 0.2 + 0.1 = 0.30000000000000004
). For this
reason, if your aggregations rely on decimal values, it's better to add logic to enforce the amount of decimal
numbers that will be displayed in the cell (see the Rounded Average on Age Column in the example below).
The next example shows many custom aggregation functions configured in a variety of ways and demonstrating different things aggregation functions can do.
The following can be noted from the example:
colDef.aggFunc
.colDef.aggFunc
.Average on Age Column
but forcing the values to display a maximum oftwo decimal numbers.
sum
aggregated function. The new sum function doesn't do anything different to the built in sum function, however it serves as a demonstration on how you can override. Maybe you want to provide a sum function that uses for example the math.js
library.gridOptions
property.gridOptions
property.cellRenderer
). the grid would complain 'Function not found' as it tries to use the function before it is set via the API.
Note that custom aggregations will get called for the top level rows to calculate a 'Grand Total', not just for row groups. For example if you have 10 rows in the grid, the grid will still call the aggregation with 10 values to get a grand total aggregation.
The grand total aggregation is normally not seen, unless the grid is configured with Grouping Total Footers. Total footers display the result of the aggregation for top level, for example displaying a grand total even if no row grouping is active.
When the grid is empty, the aggregations are still called once with an empty set. This is to calculate the grand total aggregation for the top level.
This section provides an example of how to calculate a ratio using values from multiple columns.
When values from multiple columns are required, a value object containing all the required values across multiple columns
should be passed around instead of a simple value. This value object should also contain a toString()
method, so it can
also be resolved by the grid to a single value. This is shown in the code snippet below:
const [columnDefs, setColumnDefs] = useState([
{ field: 'gold', aggFunc: 'sum' },
{ field: 'silver', aggFunc: 'sum' },
{
headerName: 'Ratio',
colId: 'ratio',
valueGetter: params => {
if (!params.node.group) {
// no need to handle group levels - calculated in the 'ratioAggFunc'
return {
gold: params.data.gold,
silver: params.data.silver,
toString: () => (gold && silver) ? gold / silver : 0,
}
}
},
aggFunc: (params) => {
var goldSum = 0;
var silverSum = 0;
params.values.forEach(value => {
if (value && value.gold) {
goldSum += value.gold;
}
if (value && value.silver) {
silverSum += value.silver;
}
});
return {
gold: goldSum,
silver: silverSum,
toString: () => {
return goldSum && silverSum ? goldSum / silverSum : 0;
},
}
}
}
]);
<AgGridReact columnDefs={columnDefs} />
The following example demonstrates this approach in action:
Using colDef.aggFunc
is the preferred way of doing aggregations. However you may find scenarios where you cannot define your aggregations with respect to individual column values. Maybe you are aggregating sales records in different currencies and you need to read the value from one column and the currency code from another column and then convert the record to a common currency for aggregation - the point being you need data from more than just one column, or you want to put the results into different columns to the inputs for the calculation. For that reason, you can take control of the row aggregation by providing a getGroupRowAgg
function as a grid callback.
Using colDef.aggFunc
is the preferred way of doing aggregations, only use getGroupRowAgg
if you cannot achieve what you want as it will make your code more complex. Also note that getGroupRowAgg
will not work when pivoting.
For groups, when aggregating, the grid stores the results in the colId of the column. For example, if you have a group defined as follows:
const [columnDefs, setColumnDefs] = useState([
{
field: 'abby',
valueGetter: 'data.a + data.b',
colId: 'aaa'
}
]);
<AgGridReact columnDefs={columnDefs} />
Then the result of the aggregation will be stored in data.aaa
and not in 'abby'. Most of the time this will not matter for you as the colId, if not provided, will default to the field. In order for the grid to display the aggregation result, it must be stored in the correct field name.
Below shows an example using getGroupRowAgg
. The example doesn't represent a real world scenario, it's contrived for demonstration. It takes the number of medals as inputs and creates two outputs, one as a normal sum and another by multiplying the result by Math.PI
.
Continue to the next section to learn about Aggregation Filtering.