Value Getter
The valueGetter function
- We can use a
valueGetterfunction get the row data for columns where the use of thefieldproperty is not an option. - We can also use the
valueGetterfunction to mutate data prior to providing the data to the grid. - The
valueGetterfunction 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 viaGridOptionsdata- 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 default function Grid() {
const [columnDefs] = useState<ColDef<RowData>[]>([
{
headerName: 'price',
valueGetter: (params) => {
if (params.data === undefined) {
return 0;
}
return Math.round(params.data.price);
},
},
]);
}
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
valueGetterto sum the total for each order.
A few hints:
- First, take a look at the
RowDatainterface 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
productcontains the price. - Use the
Array.prototype.reduce()function to sum the order.
Solution
export default function Grid() {
const [columnDefs] = useState<ColDef<RowData>[]>([
{
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);
},
},
]);
}
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 typeTthat extends aRecordwhose 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, thevalueproperty, and second, themultiplierproperty, 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
Tfor theValueGetterParams. Prior to version 28, this generic type was not available, and as a result the type definition for thedataproperty wasany. - Within the value getter function, if
dataisundefined, 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 default function Grid() {
const [columnDefs] = useState<ColDef<RowData>[]>([
{
headerName: 'price',
valueGetter: multiplierValueGetter<RowData>('price', 'taxRate'),
},
]);
}