This section covers how shared contextual information is passed to the chart elements.
Overview Copy Link
The purpose of the Context Object is to attach additional information to custom callbacks such as Formatters, Stylers and Tooltip Renderers. The Context Object is accessible via the context property in all callback and event handler parameters.
Context Object Copy Link
The Context Object can be set using the context property either at the root of the chart options, or on an individual series or axis. The series[].context and axes[].context values will be used for callbacks related to the target series or axis, but will fallback to the root context property if they are not set.
{
context: 'my root context',
series: [
{
type: 'bar',
itemStyler: ({ context }) => {
console.log(context); // prints 'my root context'
},
},
{
context: 'my series context',
type: 'bar',
itemStyler: ({ context }) => {
console.log(context); // prints 'my series context'
},
},
],
axes: {
x: {
type: 'number',
position: 'bottom',
label: {
formatter: ({ context }) => {
console.log(context); // prints 'my root context'
},
},
},
y: {
type: 'number',
position: 'left',
context: 'my axis context',
label: {
formatter: ({ context }) => {
console.log(context); // prints 'my axis context'
},
},
},
},
}In this snippet:
series[0]andaxes.xdo not have their owncontextdefined, so the callbacks use thecontextdefined at the root.series[1]andaxes.yhave customcontextvalues defined, and these will be used in callbacks.
Context Object Example Copy Link
The example below shows how the Context Object can be used.
Change the User Currency in the dropdown to update the Context Object state, which updates the tooltip and the axis labels.
import {
AgCartesianChartOptions,
AgCharts,
AnimationModule,
CandlestickSeriesModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
NumberAxisModule,
TimeAxisModule,
} from "ag-charts-enterprise";
import {
Currency,
CurrencyConverter,
makeCurrencyConverter,
} from "./currencyConverter";
import { TradeDatum, getData } from "./data";
ModuleRegistry.registerModules([
AnimationModule,
CandlestickSeriesModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
NumberAxisModule,
TimeAxisModule,
]);
const options: AgCartesianChartOptions<TradeDatum, CurrencyConverter> = {
context: makeCurrencyConverter("EUR"),
title: {
text: "Stock Prices",
},
data: getData(),
series: [
{
type: "candlestick",
xKey: "date",
openKey: "open",
highKey: "high",
lowKey: "low",
closeKey: "close",
tooltip: {
renderer: ({ datum, context }) => {
if (context == null) return {};
return {
title: datum.date.toDateString(),
data: [
{
label: "Open",
value: context.formatBothCurrencies(datum.open),
},
{
label: "High",
value: context.formatBothCurrencies(datum.high),
},
{ label: "Low", value: context.formatBothCurrencies(datum.low) },
{
label: "Close",
value: context.formatBothCurrencies(datum.close),
},
],
};
},
},
},
],
axes: {
x: {
type: "time",
},
y: {
type: "number",
label: {
formatter: ({ value, context }) => {
return context?.formatUserCurrency(value);
},
},
},
},
contextMenu: {
items: [
{
showOn: "series-node",
label: "Log as USD",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "USD")),
},
{
showOn: "series-node",
label: "Log as EUR",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "EUR")),
},
{
showOn: "series-node",
label: "Log as GBP",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "GBP")),
},
{
showOn: "series-node",
label: "Log as JPY",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "JPY")),
},
{
showOn: "series-node",
label: "Log as INR",
action: ({ datum, context }) =>
console.log(context?.formatLog(datum, "INR")),
},
],
},
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
function onMySelectChange(value: Currency) {
options.context = makeCurrencyConverter(value);
chart.update(options);
}
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).onMySelectChange = onMySelectChange;
}
import { TradeDatum } from "./data";
function unreachable(_arg: never): never {
throw new Error("");
}
export type Currency = "USD" | "EUR" | "GBP" | "JPY" | "INR";
export interface CurrencyConverter {
userCurrency: Currency;
formatCurrency(stockPrice: number, currency: Currency): string;
formatStockCurrency(stockPrice: number): string;
formatUserCurrency(stockPrice: number): string;
formatBothCurrencies(stockPrice: number): string;
formatLog(datum: TradeDatum, currency: Currency): string;
}
export function makeCurrencyConverter(
userCurrency: Currency,
): CurrencyConverter {
const self: CurrencyConverter = {
userCurrency,
formatCurrency(stockPrice: number, currency: Currency): string {
const convertedPrice = Math.floor(
USD_CONVERSION_RATES[currency] * stockPrice,
);
switch (currency) {
case "USD":
return `\$${convertedPrice}`;
case "EUR":
return `€${convertedPrice}`;
case "GBP":
return `£${convertedPrice}`;
case "JPY":
return `Â¥${convertedPrice}`;
case "INR":
return `₹${convertedPrice}`;
default:
unreachable(currency);
}
},
formatStockCurrency(stockPrice: number): string {
return this.formatCurrency(stockPrice, "USD");
},
formatUserCurrency(stockPrice: number): string {
return this.formatCurrency(stockPrice, this.userCurrency);
},
formatBothCurrencies(stockPrice: number): string {
if (this.userCurrency === "USD") {
return this.formatCurrency(stockPrice, "USD");
} else {
const stockFmt = this.formatStockCurrency(stockPrice);
const userFmt = this.formatUserCurrency(stockPrice);
return `${stockFmt} (${userFmt})`;
}
},
formatLog(datum: TradeDatum, currency: Currency): string {
return [
`Pricing in ${currency}:`,
` Open : ${this.formatCurrency(datum.open, currency)}`,
` High : ${this.formatCurrency(datum.high, currency)}`,
` Low : ${this.formatCurrency(datum.low, currency)}`,
` Close : ${this.formatCurrency(datum.close, currency)}`,
].join("\n");
},
};
return self;
}
const USD_CONVERSION_RATES: { [key in Currency]: number } = {
USD: 1,
EUR: 0.87,
GBP: 0.74,
JPY: 144,
INR: 86.06,
};
export type TradeDatum = {
date: Date;
open: number;
high: number;
low: number;
close: number;
};
export function getData() {
return [
{
date: new Date(2024, 0, 1),
open: 1200,
high: 1220,
low: 1180,
close: 1210,
},
{
date: new Date(2024, 0, 2),
open: 1210,
high: 1240,
low: 1200,
close: 1220,
},
{
date: new Date(2024, 0, 3),
open: 1220,
high: 1230,
low: 1190,
close: 1200,
},
{
date: new Date(2024, 0, 4),
open: 1200,
high: 1210,
low: 1170,
close: 1180,
},
{
date: new Date(2024, 0, 5),
open: 1180,
high: 1190,
low: 1150,
close: 1170,
},
{
date: new Date(2024, 0, 6),
open: 1170,
high: 1200,
low: 1160,
close: 1190,
},
{
date: new Date(2024, 0, 7),
open: 1190,
high: 1230,
low: 1180,
close: 1220,
},
{
date: new Date(2024, 0, 8),
open: 1220,
high: 1250,
low: 1210,
close: 1240,
},
{
date: new Date(2024, 0, 9),
open: 1240,
high: 1270,
low: 1230,
close: 1260,
},
{
date: new Date(2024, 0, 10),
open: 1260,
high: 1280,
low: 1250,
close: 1270,
},
{
date: new Date(2024, 0, 11),
open: 1270,
high: 1290,
low: 1240,
close: 1250,
},
{
date: new Date(2024, 0, 12),
open: 1250,
high: 1260,
low: 1220,
close: 1230,
},
{
date: new Date(2024, 0, 13),
open: 1230,
high: 1240,
low: 1200,
close: 1220,
},
{
date: new Date(2024, 0, 14),
open: 1220,
high: 1250,
low: 1210,
close: 1240,
},
{
date: new Date(2024, 0, 15),
open: 1240,
high: 1280,
low: 1230,
close: 1270,
},
{
date: new Date(2024, 0, 16),
open: 1270,
high: 1300,
low: 1250,
close: 1260,
},
{
date: new Date(2024, 0, 17),
open: 1260,
high: 1270,
low: 1230,
close: 1240,
},
{
date: new Date(2024, 0, 18),
open: 1240,
high: 1250,
low: 1200,
close: 1210,
},
{
date: new Date(2024, 0, 19),
open: 1210,
high: 1230,
low: 1180,
close: 1190,
},
{
date: new Date(2024, 0, 20),
open: 1190,
high: 1200,
low: 1150,
close: 1160,
},
{
date: new Date(2024, 0, 21),
open: 1160,
high: 1180,
low: 1130,
close: 1140,
},
{
date: new Date(2024, 0, 22),
open: 1140,
high: 1170,
low: 1120,
close: 1160,
},
{
date: new Date(2024, 0, 23),
open: 1160,
high: 1190,
low: 1150,
close: 1180,
},
{
date: new Date(2024, 0, 24),
open: 1180,
high: 1210,
low: 1170,
close: 1200,
},
{
date: new Date(2024, 0, 25),
open: 1200,
high: 1230,
low: 1190,
close: 1210,
},
{
date: new Date(2024, 0, 26),
open: 1210,
high: 1250,
low: 1200,
close: 1240,
},
{
date: new Date(2024, 0, 27),
open: 1240,
high: 1270,
low: 1230,
close: 1260,
},
{
date: new Date(2024, 0, 28),
open: 1260,
high: 1290,
low: 1240,
close: 1250,
},
{
date: new Date(2024, 0, 29),
open: 1250,
high: 1260,
low: 1210,
close: 1230,
},
{
date: new Date(2024, 0, 30),
open: 1230,
high: 1240,
low: 1200,
close: 1220,
},
];
}
Note that the Context Object is used by the following callbacks:
- The Y-axis Label Formatter, to convert USD values to the preferred User Currency.
- The Tooltip Renderer, to render both the stock prices in USD and the User Currency (if applicable).
- The Context Menu Actions, to log converted stock prices to the console.