LiveLoveApp logo

Value Getter

The valueGetter function

  • We can use a valueGetter function get the row data for columns where the use of the field 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 API
  • colDef - the current column definition
  • columnApi - the Column API
  • column - the current column
  • context - the application context that is set via GridOptions
  • 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 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.

  1. Open the exercise on Stackblitz.
  2. Note that the Total column is currently empty.
  3. 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 a product.
  • A product contains 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);
      },
    },
  ]);
}

See solution on Stackblitz

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 type T that extends a Record whose values are of type number. The higher-order function will return the value getter function that will be invoked by AG Grid with provided ValueGetterParams<T>.
  • The multiplierValueGetter() has two required parameters, first, the value property, and second, the multiplier property, both of which are keys of the data provided to the grid that is of type T.
  • Because we are using AG Grid v28 (or greater) we can specify the generic type of T for the ValueGetterParams. Prior to version 28, this generic type was not available, and as a result the type definition for the data property was any.
  • Within the value getter function, if data is undefined, which can be the case when using infinite row model or row grouping in AG Grid, we return 0.
  • 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'),
    },
  ]);
}

See example Stackblitz