Value Getter
The valueGetter
function
- We can use a
valueGetter
function get the row data for columns where the use of thefield
property is not an option. - We can also use the
valueGetter
function to mutate data prior to providing the data to the grid. - The
valueGetter
function is invoked by AG Grid for each cell. - The function is invoked with the
ValueGetterParams<TData>
object.
Before we dive into using the valueGetter
, let's look at the ValueGetterParams<TData>
interface.
export interface ValueGetterParams<TData = any> {
api: GridApi<TData>;
colDef: ColDef<TData>;
column: Column;
columnApi: ColumnApi;
context: any;
data: TData | undefined;
getValue: (field: string) => any;
node: RowNode<TData> | null;
}
Let's break down each property:
api
- the Grid APIcolDef
- the current column definitioncolumnApi
- the Column APIcolumn
- the current columncontext
- the application context that is set viaGridOptions
data
- the data for the current row (node)getValue()
- a utility method for getting column values (dot-notation accepted here)node
- the row node for the current row
Grid API
The Grid API is extremely useful for:
- Programmatically interacting with the Grid
- Adding event listeners to the Grid
- Accessing the clipboard features
- And lots more!
Column API
The Column API is extremely useful for:
- Programmatically interacting with a specific column
- Moving, pinning, sizing, etc. a column
- And lots more!
What is a row node?
- A row node represents a single row in the grid
- Row selection API
- Updating row data
- Adding event listeners to the row
Ok, now that we have learned about how a valueGetter
is invoked by AG Grid, let's take a quick look at an example.
export class GridComponent {
columnDefs = [
{
headerName: 'price',
valueGetter: (params) => {
if (params.data === undefined) {
return 0;
}
return Math.round(params.data.price);
}
},
] as ColDef<RowData>[];
}
Exercise
The goal of this exercise is to learn how to use the valueGetter
function.
- Open the exercise on Stackblitz.
- Note that the Total column is currently empty.
- Use a
valueGetter
to sum the total for each order.
A few hints:
- First, take a look at the
RowData
interface to gain an understanding of the data model. - Each row in the grid represents an order.
- An order is associated with
orderItems
, which associate each item with aproduct
. - A
product
contains the price. - Use the
Array.prototype.reduce()
function to sum the order.
Solution
export class GridComponent {
columnDefs = [
{
headerName: 'Total',
filter: 'agNumberColumnFilter',
valueGetter: (params) => {
if (!params.data) {
return null;
}
const orderItems = params.data.orderItems;
return orderItems
.filter((item) => item.orderId === params.data.id)
.map((item) =>
products.find((product) => product.id === item.productId)
)
.reduce((prev, current) => prev + Number(current.price), 0);
},
},
] as ColDef<RowData>[];
}
Reusable Value Getters
Providing the valueGetter
function inline is perfectly reasonable.
However, we may want to have a more reusable solution.
Let's look at example of a higher-order multiplierValueGetter
function:
export const multiplierValueGetter =
<T extends Record<TKey, number>,
TKey extends string | number | symbol = string>(
value: keyof T,
multiplier: keyof T
) =>
(params: ValueGetterParams<T>): number => {
if (params.data === undefined) {
return 0;
}
return Math.round(params.data[value] * params.data[multiplier] * 100) / 100;
};
Let's review the code:
- First, we declare the
multiplierValueGetter()
higher-order function. Using a higher-order function enables us to define the generic typeT
that extends aRecord
whose values are of typenumber
. The higher-order function will return the value getter function that will be invoked by AG Grid with providedValueGetterParams<T>
. - The
multiplierValueGetter()
has two required parameters, first, thevalue
property, and second, themultiplier
property, both of which are keys of the data provided to the grid that is of typeT
. - Because we are using AG Grid v28 (or greater) we can specify the generic type of
T
for theValueGetterParams
. Prior to version 28, this generic type was not available, and as a result the type definition for thedata
property wasany
. - Within the value getter function, if
data
isundefined
, which can be the case when using infinite row model or row grouping in AG Grid, we return0
. - Finally, we can round the value after multiplying.
Here is an example implementation of our multiplierValueGetter()
higher-order function.
export class GridComponent {
columnDefs = [
{
headerName: 'price',
valueGetter: multiplierValueGetter<RowData>('price', 'taxRate'),
},
] as ColDef<RowData>[];
}