LiveLoveApp logo

Value Formatter

The valueFormatter function

  • After the cell value is known, the optional valueFormatter() callback function enables us to format the value.
  • The valueFormatter function is invoked by AG Grid for each cell.
  • The function is invoked with the ValueFormatterParams<TData, TValue> object.

Before we dive into using the valueFormatter, let's look at the ValueFormatterParams<TData, TValue> interface.

export interface ValueFormatterParams<TData = any, TValue = any> {
  api: GridApi<TData>;
  colDef: ColDef<TData>;
  column: Column;
  columnApi: ColumnApi;
  context: any;
  data: TData | undefined;
  node: RowNode<TData> | null;
  value: TValue;
}

The main difference between the ValueFormatterParams and the ValueGetterParams interfaces are:

  • The getValue() utility method is not available.
  • Rather, we are provided with the value of the cell to be formatted.

Let's look at an example:

export default function Grid() {
  const [columnDefs] = useState<ColDef<RowData>[]>([
    {
      headerName: 'price',
      valueFormatter: (params) => {
        const formatter = new Intl.NumberFormat('en-US', {
          minimumFractionDigits: digits,
          maximumFractionDigits: digits,
        });
        if (params.value === undefined) {
          return formatter.format(0);
        }
        return formatter.format(Number(params.value));
      },
    },
  ]);
}

Exercise

The goal of this exercise is to learn how to use the valueGetter function.

  1. Open the exercise on Stackblitz.
  2. Add a valueFormatter to the Total column to format the value using the Intl.NumberFormat class

Solution

export default function Grid() {
  const [columnDefs] = useState<ColDef<RowData>[]>([
    {
      headerName: 'Total',
      field: 'total',
      filter: 'agNumberColumnFilter',
      valueFormatter: (params) => {
        if (!params.data) {
          return '0';
        }
        return new Intl.NumberFormat('en-US', {
          style: 'currency',
          currency: 'USD',
        }).format(params.value);
      },
    },
  ]);
}

See solution on Stackblitz

Reusable Value Formatters

Similar to how we learned to use a higher-order function for reusable value getters, let's look at an example of a reusable value formatter:

export const decimalValueFormatter =
  <TData, TValue>(digits = 0) =>
  (params: ValueFormatterParams<TData, TValue>): string => {
    const formatter = new Intl.NumberFormat('en-US', {
      minimumFractionDigits: digits,
      maximumFractionDigits: digits,
    });
    if (params.value === undefined) {
      return formatter.format(0);
    }
    return formatter.format(Number(params.value));
  };

Let's review the code:

  • We have declared a decimalValueFormatter() higher-order function. This enables the implementation of this value formatter to specify two generic types: TData and TValue. The generic of TData represents the type for the data parameter, and the generic of TValue represents the type for the value parameter. Our higher-order function has an optional digits parameter that specifies the min and maximum number of digits for the decimal formatting. The higher-order function returns a function that is the value getter that is invoked by AG Grid with the ValueGetterParams<TData, TValue> object.
  • In this value formatter, we are using the Intl.NumberFormat class to create a new formatter instance, specifying the minimum and maximum number of fraction digits.
  • If the data is undefined, which can be the case when using infinite row model or row grouping in AG Grid, then we simply return 0.
  • Otherwise, we return the formatted value.

Here is an example implementation of our decimalValueFormatter() higher-order function.

export default function Grid() {
  const [columnDefs] = useState<ColDef<RowData>[]>([
    {
      headerName: 'price',
      valueFormatter: decimalValueFormatter<RowData, Pick<RowData, 'price'>>(2),
    },
  ]);
}

See example Stackblitz