---
product: "AG Grid"
title: "Context"
description: "This sections covers how shared contextual information can be passed around the grid."
framework: angular
version: "36.2.0"
related:
    - title: "Grid State"
      url: "https://www.ag-grid.com/archive/36.2.0/angular-data-grid/grid-state/"
    - title: "Grid Lifecycle"
      url: "https://www.ag-grid.com/archive/36.2.0/angular-data-grid/grid-lifecycle/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Context

This sections covers how shared contextual information can be passed around the grid.

## Overview

The context object is passed to all callbacks and events used in the grid. The purpose of the context object is to allow the client application to pass details to custom callbacks such as the [Cell Renderers](https://www.ag-grid.com/archive/36.2.0/angular-data-grid/component-cell-renderer/) and [Cell Editors](https://www.ag-grid.com/archive/36.2.0/angular-data-grid/cell-editing/).

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `context` | `any` |  |  |  |

To update the context call `api.setGridOption` with the new context. Alternatively, if you maintain a reference to the context object it's values can be mutated directly.

Updating the context does **not** refresh the grid. The grid has no way of knowing which callbacks read which parts of the context, so the application must refresh whatever depends on it: `api.refreshCells()` re-runs value getters, cell class rules and cell renderers, `api.refreshHeader()` re-runs header value getters, and `api.refreshClientSideRowModel('aggregate')` recalculates aggregated values.

## Typing the Context

The `context` grid option is typed as `any`, so apply your own interface to it using `as`. That interface is then supplied to the `TContext` generic parameter of each callback or event interface that reads from the context, which types `params.context`.

```js
interface IReportingContext {
    reportingCurrency: 'EUR' | 'GBP' | 'USD';
}

const gridOptions: GridOptions<IProduct> = {
    context: {
        reportingCurrency: 'EUR',
    } as IReportingContext,

    // other grid options ...
};

// TContext is the last generic parameter of ValueGetterParams<TData, TValue, TContext>
function reportingCurrencyValueGetter(params: ValueGetterParams<IProduct, IPrice, IReportingContext>) {
    // params.context.reportingCurrency is typed as 'EUR' | 'GBP' | 'USD'
    const reportingCurrency = params.context.reportingCurrency;
    // ...
}
```

`TContext` is always the last generic parameter of the interface and defaults to `any` when omitted, so it must be provided explicitly at each usage — unlike `TData`, it cannot be inferred from the grid options. See [TypeScript Generics](https://www.ag-grid.com/archive/36.2.0/angular-data-grid/typescript-generics/#context-tcontext) for how the grid's generic parameters fit together.

## Context Object Example

The example below demonstrates how the context object can be used. Note the following:

- Selecting the reporting currency from the dropdown places it in the context object.
- When the reporting currency is changed the cell renderer uses the currency supplied in the context object to calculate the value using: `params.context.reportingCurrency`.
- The price column header is updated to show the selected currency using a header value getter using `ctx.reportingCurrency`.
- Changing the context alone would leave the grid showing stale values, so `api.refreshCells()` and `api.refreshHeader()` are called afterwards to re-run the value getter and the header value getter.
- The context is typed via the `IReportingContext` interface, supplied to the `TContext` generic parameter of `ValueGetterParams` and `ICellRendererParams`.

#### Context Object

```ts
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  HighlightChangesModule,
  ICellRendererParams,
  ModuleRegistry,
  RenderApiModule,
  ValueGetterParams,
  enableDevValidations,
} from "ag-grid-community";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableDevValidations();
}

ModuleRegistry.registerModules([
  RenderApiModule,
  HighlightChangesModule,
  ClientSideRowModelModule,
]);

interface IPrice {
  currency: Currency;
  amount: number;
}
interface IProduct {
  product: string;
  price: IPrice;
}
interface IReportingContext {
  reportingCurrency: Currency;
}

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div style="height: 10%">
      <select id="currency" (change)="currencyChanged()">
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
        <option value="USD">USD</option>
      </select>
    </div>
    <ag-grid-angular
      style="width: 100%; height: 90%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [rowData]="rowData"
      [context]="context"
      (gridReady)="onGridReady($event)"
    /> `,
})
export class AppComponent {
  private gridApi!: GridApi<IProduct>;

  columnDefs: ColDef[] = [
    { field: "product" },
    { headerName: "Currency", field: "price.currency" },
    {
      headerName: "Price Local",
      field: "price",
      cellRenderer: currencyCellRenderer,
      comparator: currencyComparator,
      cellDataType: false,
    },
    {
      headerName: "Report Price",
      field: "price",
      cellRenderer: currencyCellRenderer,
      comparator: currencyComparator,
      valueGetter: reportingCurrencyValueGetter,
      headerValueGetter: "ctx.reportingCurrency",
    },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    enableCellChangeFlash: true,
  };
  rowData: IProduct[] | null = getData();
  context: any = {
    reportingCurrency: "EUR",
  } as IReportingContext;

  currencyChanged() {
    const value = (document.getElementById("currency") as HTMLSelectElement)
      .value as Currency;
    this.gridApi.setGridOption("context", {
      reportingCurrency: value,
    } as IReportingContext);
    // Changing the context does not refresh the grid on its own - the cells and
    // headers that read from it must be refreshed explicitly.
    this.gridApi.refreshCells();
    this.gridApi.refreshHeader();
  }

  onGridReady(params: GridReadyEvent<IProduct>) {
    this.gridApi = params.api;
  }
}

const formatters: Record<Currency, Intl.NumberFormat> = {
  EUR: new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "EUR",
    minimumFractionDigits: 2,
  }),
  GBP: new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "GBP",
    minimumFractionDigits: 2,
  }),
  USD: new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits: 2,
  }),
};
const currencyComparator = (a: IPrice, b: IPrice) => {
  return a.amount - b.amount;
};
const currencyCellRenderer = (
  params: ICellRendererParams<IProduct, IPrice, IReportingContext>,
) => {
  const price = params.value;
  if (!price) {
    return "";
  }
  return formatters[price.currency]?.format(price.amount) ?? price.amount;
};
// Rates taken from google at time of writing
const exchangeRates: Record<Currency, Partial<Record<Currency, number>>> = {
  EUR: { GBP: 0.72, USD: 1.08 },
  GBP: { EUR: 1.29, USD: 1.5 },
  USD: { GBP: 0.67, EUR: 0.93 },
};
function reportingCurrencyValueGetter(
  params: ValueGetterParams<IProduct, IPrice, IReportingContext>,
): IPrice {
  const price = params.data!.price;
  // params.context is typed as IReportingContext, so reportingCurrency is typed as Currency
  const reportingCurrency = params.context.reportingCurrency;
  const fxRate = exchangeRates[reportingCurrency][price.currency];
  return {
    currency: reportingCurrency,
    amount: fxRate ? price.amount * fxRate : price.amount,
  };
}
function getData(): IProduct[] {
  return [
    { product: "Product 1", price: { currency: "EUR", amount: 644 } },
    { product: "Product 2", price: { currency: "EUR", amount: 354 } },
    { product: "Product 3", price: { currency: "GBP", amount: 429 } },
    { product: "Product 4", price: { currency: "GBP", amount: 143 } },
    { product: "Product 5", price: { currency: "USD", amount: 345 } },
    { product: "Product 6", price: { currency: "USD", amount: 982 } },
  ];
}
```

[Live example: Context Object](https://www.ag-grid.com/archive/36.2.0/examples/context/context/angular/)

## Context & Expressions Example

Below shows a complex example making use of value getters (using expressions) and class rules (again using expressions). The grid shows 'actual vs budget data and yearly total' for widget sales split by city and country.

- The **Location** column is showing the aggregation groups, grouping by city and country.
- The **Monthly Data** columns are affected by the context. Depending on the selected period, the data displayed is either actual (`x_act`) or budgeted (`x_bud`) data for the month (eg. `jan_act` when Jan is green, or `jan_bud` when Jan is red). Similarly, the background color is also changed using class rules dependent on the selected period.
- **sum(YTD)** is the total of the 'actual' figures, i.e. adding up all the green. This also changes as the period is changed.
- Changing the period mutates `context.month` in place and then calls `api.refreshClientSideRowModel('aggregate')` and `api.refreshCells()` to recalculate the aggregations and re-render the affected cells.

Notice that the example (including calculating the expression on the fly, the grid only calculates what's needed to be displayed) runs very fast (once the data is loaded) despite having over 6,000 rows.

This example is best viewed by opening it in a new tab.

#### Monthly Sales

```ts
import { HttpClient } from "@angular/common/http";
import { Component } from "@angular/core";

import { AgGridAngular } from "ag-grid-angular";
import type {
  ColDef,
  ColGroupDef,
  GridApi,
  GridReadyEvent,
  ICellRendererParams,
  RowSelectionOptions,
} from "ag-grid-community";
import {
  CellStyleModule,
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  ModuleRegistry,
  QuickFilterModule,
  RenderApiModule,
  RowSelectionModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  FiltersToolPanelModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";

import "./styles.css";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelApiModule,
  RenderApiModule,
  RowSelectionModule,
  CellStyleModule,
  ClientSideRowModelModule,
  QuickFilterModule,
  RowGroupingModule,
  SetFilterModule,
  FiltersToolPanelModule,
]);

@Component({
  standalone: true,
  imports: [AgGridAngular],
  selector: "my-app",
  template: `<div class="test-container">
    <div class="test-header">
      <input
        type="text"
        id="filter-text-box"
        style="width: 100px;"
        (input)="onQuickFilterChanged()"
        placeholder="Filter..."
      />

      <span style="padding-left: 20px;">
        <b>Period:</b>
        <button (click)="onChangeMonth(-1)">
          <i class="fa fa-chevron-left"></i>
        </button>
        <button (click)="onChangeMonth(1)">
          <i class="fa fa-chevron-right"></i>
        </button>
        <span id="monthName" style="width: 100px; display: inline-block;"
          >Year to Jan</span
        >
      </span>

      <span style="padding-left: 20px;">
        <b>Legend:</b>&nbsp;&nbsp;
        <div class="cell-bud legend-box"></div>
        Actual&nbsp;&nbsp;
        <div class="cell-act legend-box"></div>
        Budget
      </span>
    </div>
    <ag-grid-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      suppressMovableColumns
      [context]="context"
      [defaultColDef]="defaultColDef"
      [autoGroupColumnDef]="autoGroupColumnDef"
      [rowSelection]="rowSelection"
      [rowData]="rowData"
      (gridReady)="onGridReady($event)"
    />
  </div>`,
})
export class AppComponent {
  private gridApi!: GridApi;

  public columnDefs: (ColDef | ColGroupDef)[] = [
    {
      field: "country",
      rowGroup: true,
      hide: true,
    },
    {
      headerName: "Monthly Data",
      children: [
        {
          field: "jan",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "feb",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "mar",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "apr",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "may",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "jun",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          headerName: "YTD",
          cellClass: "cell-figure",
          cellRenderer: accountingCellRenderer,
          valueGetter: yearToDateValueGetter,
          aggFunc: "sum",
        },
      ],
    },
  ];
  public context: any = {
    month: 0,
    months: [
      "jan",
      "feb",
      "mar",
      "apr",
      "may",
      "jun",
      "jul",
      "aug",
      "sep",
      "oct",
      "nov",
      "dec",
    ],
  };
  public defaultColDef: ColDef = {
    flex: 1,
    minWidth: 120,
  };
  public autoGroupColumnDef: ColDef = {
    headerName: "Location",
    field: "city",
    minWidth: 260,
    cellRenderer: "agGroupCellRenderer",
  };
  public rowSelection: RowSelectionOptions = {
    mode: "multiRow",
    headerCheckbox: false,
    groupSelects: "descendants",
  };
  public rowData!: any[];

  constructor(private http: HttpClient) {}

  onChangeMonth(i: number) {
    let newMonth = (this.context.month += i);
    if (newMonth < -1) {
      newMonth = -1;
    }
    if (newMonth > 5) {
      newMonth = 5;
    }
    // Mutate the context object in place
    this.context.month = newMonth;
    document.querySelector("#monthName")!.textContent =
      monthNames[newMonth + 1];
    this.gridApi.refreshClientSideRowModel("aggregate");
    this.gridApi.refreshCells();
  }

  onQuickFilterChanged() {
    this.gridApi.setGridOption(
      "quickFilterText",
      (document.getElementById("filter-text-box") as HTMLInputElement).value,
    );
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;

    this.http
      .get<any[]>("https://www.ag-grid.com/example-assets/monthly-sales.json")
      .subscribe((data) => {
        this.rowData = data;
      });
  }
}

const monthValueGetter =
  '(ctx.month < ctx.months.indexOf(colDef.field)) ? data[colDef.field + "_bud"] : data[colDef.field + "_act"]';
const monthCellClassRules = {
  "cell-act": "ctx.month < ctx.months.indexOf(colDef.field)",
  "cell-bud": "ctx.month >= ctx.months.indexOf(colDef.field)",
  "cell-negative": "x < 0",
};
const yearToDateValueGetter =
  'var total = 0; ctx.months.forEach( function(monthName, monthIndex) { if (monthIndex<=ctx.month) { total += data[monthName + "_act"]; } }); return total; ';
const accountingCellRenderer = function (params: ICellRendererParams) {
  if (params.value == null) {
    return "";
  } else if (params.value >= 0) {
    return params.value.toLocaleString();
  } else {
    return "(" + Math.abs(params.value).toLocaleString() + ")";
  }
};
const monthNames = [
  "Budget Only",
  "Year to Jan",
  "Year to Feb",
  "Year to Mar",
  "Year to Apr",
  "Year to May",
  "Year to Jun",
  "Year to Jul",
  "Year to Aug",
  "Year to Sep",
  "Year to Oct",
  "Year to Nov",
  "Full Year",
];
```

[Live example: Monthly Sales](https://www.ag-grid.com/archive/36.2.0/examples/context/monthly-sales/angular/)
