This section explains how to listen and respond to various chart and series events.
Chart Events Copy Link
These events are raised by interactions across the entire chart.
click and doubleClick Copy Link
These are fired on click or double-click on any empty part of the chart. When a user double-clicks, the click event will be fired on the first click, then both the click and doubleClick will be fired on the second click.
These events may be prevented by other clickable parts of the chart, such as series nodes and legend items which have their own events.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgChartClickEvent,
AgChartDoubleClickEvent,
AgChartOptions,
BarSeriesModule,
CategoryAxisModule,
LegendModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
ModuleRegistry.registerModules([
BarSeriesModule,
CategoryAxisModule,
LegendModule,
NumberAxisModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgChartOptions>({
title: {
text: "Number of Cars Sold",
},
subtitle: {
text: "(single or double click empty space outside bars)",
},
data: [
{ month: "March", units: 25, brands: { BMW: 10, Toyota: 15 } },
{ month: "April", units: 27, brands: { Ford: 17, BMW: 10 } },
{ month: "May", units: 42, brands: { Nissan: 20, Toyota: 22 } },
],
series: [
{
type: "bar",
xKey: "month",
yKey: "units",
},
],
listeners: {
click: (_event: AgChartClickEvent) => {
console.log("[click]");
},
doubleClick: (_event: AgChartDoubleClickEvent) => {
console.log("[double click]");
},
},
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
In this example:
- When a blank area on a chart is clicked, a message is shown in the console.
- When a blank area on a chart is double-clicked, a different message is shown.
seriesNodeClick and seriesNodeDoubleClick Copy Link
These are fired on click or double-click of any series node in the chart.
The contents of the event object passed to the listener will depend on the type of series the clicked node belongs to.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgChartOptions,
BarSeriesModule,
CategoryAxisModule,
LegendModule,
LineSeriesModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
import { DataType, getData } from "./data";
ModuleRegistry.registerModules([
BarSeriesModule,
CategoryAxisModule,
LegendModule,
LineSeriesModule,
NumberAxisModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgChartOptions<DataType>>({
title: {
text: "Average low/high temperatures in London",
},
subtitle: {
text: "(click a data point for details)",
},
data: getData(),
series: [
{
type: "line",
xKey: "month",
yKey: "high",
},
{
type: "bar",
xKey: "month",
yKey: "low",
},
],
legend: {
enabled: false,
},
listeners: {
seriesNodeClick: ({ datum, yKey, seriesId }) => {
console.log(
`[click]\nTemperature in ${datum.month}: ${String(datum[yKey!])}°C\nSeries: ${seriesId}`,
);
},
seriesNodeDoubleClick: ({ datum, yKey, seriesId }) => {
const celsius = Number(datum[yKey!]);
const fahrenheit = (celsius * 9) / 5 + 32;
console.log(
`[double click]\nTemperature in ${datum.month}: ${fahrenheit.toFixed(2)}°F\nSeries: ${seriesId}`,
);
},
},
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
export interface DataType {
month: string;
low: number;
high: number;
}
export function getData(): DataType[] {
return [
{ month: "March", low: 3.9, high: 11.3 },
{ month: "April", low: 5.5, high: 14.2 },
{ month: "May", low: 8.7, high: 17.9 },
];
}
In this example:
- Whenever a column or line marker is clicked, information about that series node is shown in the console.
- Whenever a column or line marker is double-clicked, the information is shown with temperatures in Fahrenheit.
- The ID of the series that contains the clicked node is also logged.
seriesVisibilityChange Copy Link
This is fired when the visibility of a series or data item is toggled. This is usually triggered by user interaction with a legend item.
This event contains:
- The
seriesIdof the series. - The
itemId,legendItemNameor other identifiers of the changed item. visible- the new visibility state of the series or item.
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgChartLegendClickEvent,
AgPolarChartOptions,
AgSeriesVisibilityChange,
LegendModule,
ModuleRegistry,
PieSeriesModule,
} from "ag-charts-community";
let counter = 1;
ModuleRegistry.registerModules([LegendModule, PieSeriesModule]);
const ChartExample = () => {
const [options, setOptions] = useState<AgPolarChartOptions>({
title: { text: "Business Expense Distribution" },
data: [
{ expense: "Salaries", percentage: 40 },
{ expense: "Office Rent", percentage: 20 },
{ expense: "Marketing", percentage: 15 },
{ expense: "Research & Development", percentage: 10 },
{ expense: "Utilities & Miscellaneous", percentage: 10 },
{ expense: "Travel", percentage: 5 },
],
series: [{ type: "pie", angleKey: "percentage", legendItemKey: "expense" }],
legend: {
listeners: {
legendItemClick: (event: AgChartLegendClickEvent) => {
counter = (counter + 1) % 2;
document.getElementById("myCounter")!.textContent = `${counter}`;
if (counter !== 1) {
event.preventDefault();
}
},
},
},
listeners: {
seriesVisibilityChange: ({
seriesId,
itemId,
legendItemName,
visible,
}: AgSeriesVisibilityChange) => {
console.log(
`seriesId: ${seriesId}, itemId: ${itemId}, legendItemName: ${legendItemName}, visible: ${visible}`,
);
},
},
});
return (
<Fragment>
<div className="example-controls">
<div className="controls-row center">
Counter: <span id="myCounter">1</span>
</div>
</div>
<AgCharts options={options} />
</Fragment>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
{
listeners: {
seriesVisibilityChange: ({ seriesId, visible }) => {
console.log(`seriesId: ${seriesId}, visible: ${visible}`);
},
},
}In this example:
- When a legend item is clicked, the visibility change is prevented and a counter decreases. This is done by using
preventDefaulton the legendItemClick event. - When the counter hits zero, the series toggle is allowed to occur.
- The series visibility change is fired, with the relevant information shown in the console.
activeChange Copy Link
This event is fired when the active state is changed. This occurs when a user interaction (mouse, touch, keyboard) on a series node or legend causes a highlight or tooltip change.
The event contains:
activeItem- the item that is now active, orundefinedif no item is active.- The
activeItemcontains:type- the type of the active item, either'series-node'or'legend'.seriesIdanditemIdidentifying the active item.
datum- the data from the chart data array for the active item.source- the source of the event, either'user-interaction'or'state-change'.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgActiveChangeEvent,
AgChartOptions,
BarSeriesModule,
CategoryAxisModule,
LegendModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
import { getData } from "./data";
ModuleRegistry.registerModules([
BarSeriesModule,
LegendModule,
CategoryAxisModule,
NumberAxisModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgChartOptions>({
title: {
text: "Energy Production by Source & Country",
},
subtitle: {
text: "Energy Production (TWh)",
},
data: getData(),
series: [
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "USACoal",
yName: "Coal - USA",
legendItemName: "Coal",
stackGroup: "usa",
fill: "#5b5b5b",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "USAGas",
yName: "Natural Gas - USA",
legendItemName: "Natural Gas",
stackGroup: "usa",
fill: "#f2a541",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "USARenewables",
yName: "Renewables - USA",
legendItemName: "Renewables",
stackGroup: "usa",
fill: "#4caf50",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "USANuclear",
yName: "Nuclear - USA",
legendItemName: "Nuclear",
stackGroup: "usa",
fill: "#6f7bd9",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "GermanyCoal",
yName: "Coal - Germany",
legendItemName: "Coal",
stackGroup: "germany",
showInLegend: false,
fill: "#5b5b5b",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "GermanyGas",
yName: "Natural Gas - Germany",
legendItemName: "Natural Gas",
stackGroup: "germany",
showInLegend: false,
fill: "#f2a541",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "GermanyRenewables",
yName: "Renewables - Germany",
legendItemName: "Renewables",
stackGroup: "germany",
showInLegend: false,
fill: "#4caf50",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "GermanyNuclear",
yName: "Nuclear - Germany",
legendItemName: "Nuclear",
stackGroup: "germany",
showInLegend: false,
fill: "#6f7bd9",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "ChinaCoal",
yName: "Coal - China",
legendItemName: "Coal",
stackGroup: "china",
showInLegend: false,
fill: "#5b5b5b",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "ChinaGas",
yName: "Natural Gas - China",
legendItemName: "Natural Gas",
stackGroup: "china",
showInLegend: false,
fill: "#f2a541",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "ChinaRenewables",
yName: "Renewables - China",
legendItemName: "Renewables",
stackGroup: "china",
showInLegend: false,
fill: "#4caf50",
},
{
type: "bar",
direction: "horizontal",
xKey: "year",
yKey: "ChinaNuclear",
yName: "Nuclear - China",
legendItemName: "Nuclear",
stackGroup: "china",
showInLegend: false,
fill: "#6f7bd9",
},
],
listeners: {
activeChange: (ev: AgActiveChangeEvent<unknown, unknown>) => {
if (ev.activeItem === undefined) {
console.log(`[inactive], event:`, ev);
} else {
const { type: t, seriesId: s, itemId: i } = ev.activeItem;
console.log(`[${t}], seriesId: ${s}, itemId: ${i}, event:`, ev);
}
},
},
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
export function getData() {
return [
{
year: 2024,
USACoal: 900,
USAGas: 1600,
USARenewables: 800,
USANuclear: 780,
GermanyCoal: 420,
GermanyGas: 500,
GermanyRenewables: 620,
GermanyNuclear: 60,
ChinaCoal: 4200,
ChinaGas: 350,
ChinaRenewables: 1400,
ChinaNuclear: 420,
},
{
year: 2025,
USACoal: 850,
USAGas: 1650,
USARenewables: 900,
USANuclear: 790,
GermanyCoal: 380,
GermanyGas: 480,
GermanyRenewables: 700,
GermanyNuclear: 40,
ChinaCoal: 4000,
ChinaGas: 380,
ChinaRenewables: 1600,
ChinaNuclear: 450,
},
{
year: 2026,
USACoal: 800,
USAGas: 1700,
USARenewables: 1050,
USANuclear: 800,
GermanyCoal: 320,
GermanyGas: 460,
GermanyRenewables: 820,
GermanyNuclear: 0,
ChinaCoal: 3800,
ChinaGas: 420,
ChinaRenewables: 1900,
ChinaNuclear: 500,
},
];
}
{
listeners: {
activeChange: (ev) => {
if (ev.activeItem === undefined) {
console.log(`[inactive], event:`, ev);
} else {
const { type: t, seriesId: s, itemId: i } = ev.activeItem;
console.log(`[${t}], seriesId: ${s}, itemId: ${i}, event:`, ev);
}
},
},
}In this example:
- Whenever a user interaction (mouse, touch, keyboard) on the series-area or legend changes the highlight state, a message is shown in the console.
selectionChange Copy Link
This is fired when the Data Selection is updated by either user interaction or an API call. See Selection Change Event for full details.
collapsedChange Copy Link
This is fired when an item in an Org Chart is expanded or collapsed, by either user interaction or an API call.
The event contains:
collapsed- array of the items newly collapsed by this change, each withitemIdanddatum:itemId- the unique identifier of the datum.datum- the data from the chart data array for the collapsed item.
expanded- array of the items newly expanded by this change, each withitemIdanddatum:itemId- the unique identifier of the datum.datum- the data from the chart data array for the expanded item.
source- the source of the event, either'user-interaction'or'api-call'.
collapsed and expanded contain only the items changed by this event, not the full set of collapsed or expanded items. Use chart.getState() to get the current state of all items.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgChartOptions,
ContextMenuModule,
ModuleRegistry,
OrganizationSeriesModule,
} from "ag-charts-enterprise";
import { getData } from "./data";
ModuleRegistry.registerModules([OrganizationSeriesModule, ContextMenuModule]);
const ChartExample = () => {
const [options, setOptions] = useState<AgChartOptions>({
title: {
text: "Company Organisation",
},
data: getData(),
listeners: {
collapsedChange: (event) => {
console.log(
`source: ${event.source},`,
"just collapsed:",
event.collapsed.map(({ itemId }) => itemId),
"just expanded:",
event.expanded.map(({ itemId }) => itemId),
);
},
},
initialState: {
collapsed: [
"Mr. Jeffrey Brown",
"Nicole Jones",
"Justin Contreras",
"Lawrence Martinez",
"Eric Jensen",
],
},
series: [
{
type: "organization",
idKey: "id",
parentIdKey: "parentId",
node: {
image: {
key: "avatar",
height: 50,
width: 50,
position: "left",
},
title: { key: "name" },
subtitle: { key: "job" },
labels: [{ key: "location" }],
},
},
],
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
export function getData() {
return [
{
id: "Ashley Rivers",
parentId: null,
name: "Ashley Rivers",
job: "CEO",
department: "Executive",
location: "France",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/19.webp",
},
{
id: "Joseph Howe",
parentId: "Ashley Rivers",
name: "Joseph Howe",
job: "CTO",
department: "Technology",
location: "United States",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/20.webp",
},
{
id: "Mr. Jeffrey Brown",
parentId: "Joseph Howe",
name: "Mr. Jeffrey Brown",
job: "Design",
department: "Technology",
location: "France",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/22.webp",
},
{
id: "Melissa Vazquez",
parentId: "Mr. Jeffrey Brown",
name: "Melissa Vazquez",
job: "Design",
department: "Technology",
location: "France",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/2.webp",
},
{
id: "John Thomas",
parentId: "Mr. Jeffrey Brown",
name: "John Thomas",
job: "Design",
department: "Technology",
location: "Netherlands",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/5.webp",
},
{
id: "Nicole Jones",
parentId: "Joseph Howe",
name: "Nicole Jones",
job: "Exec. Vice President",
department: "Technology",
location: "Portugal",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/29.webp",
},
{
id: "James Long",
parentId: "Nicole Jones",
name: "James Long",
job: "Design",
department: "Technology",
location: "Netherlands",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/25.webp",
},
{
id: "Susan Hernandez",
parentId: "Nicole Jones",
name: "Susan Hernandez",
job: "Design",
department: "Technology",
location: "Ireland",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/7.webp",
},
{
id: "Justin Contreras",
parentId: "Joseph Howe",
name: "Justin Contreras",
job: "Design",
department: "Technology",
location: "Italy",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/10.webp",
},
{
id: "Rachel Ibarra",
parentId: "Justin Contreras",
name: "Rachel Ibarra",
job: "Design",
department: "Technology",
location: "Italy",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/2.webp",
},
{
id: "John Gomez",
parentId: "Justin Contreras",
name: "John Gomez",
job: "Design",
department: "Technology",
location: "France",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/17.webp",
},
{
id: "Gary Garcia",
parentId: "Ashley Rivers",
name: "Gary Garcia",
job: "Head of Department",
department: "Operations",
location: "Netherlands",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/18.webp",
},
{
id: "Lawrence Martinez",
parentId: "Gary Garcia",
name: "Lawrence Martinez",
job: "Design",
department: "Operations",
location: "United States",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/33.webp",
},
{
id: "Devin Pittman",
parentId: "Lawrence Martinez",
name: "Devin Pittman",
job: "Design",
department: "Operations",
location: "United Kingdom",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/18.webp",
},
{
id: "Emily Barajas",
parentId: "Lawrence Martinez",
name: "Emily Barajas",
job: "Design",
department: "Operations",
location: "Italy",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/28.webp",
},
{
id: "Eric Jensen",
parentId: "Gary Garcia",
name: "Eric Jensen",
job: "Design",
department: "Operations",
location: "Spain",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/35.webp",
},
{
id: "Michael Morris",
parentId: "Eric Jensen",
name: "Michael Morris",
job: "Design",
department: "Operations",
location: "France",
status: "In Office",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/10.webp",
},
{
id: "Jodi Miller",
parentId: "Eric Jensen",
name: "Jodi Miller",
job: "Design",
department: "Operations",
location: "Italy",
status: "Remote",
avatar: "https://www.ag-grid.com/charts/example-assets/docs-images/hr/30.webp",
},
];
}
In this example:
- Whenever a node is collapsed or expanded, a message is shown in the console.
annotations Copy Link
This is fired when the annotations are changed, added or removed in either cartesian charts or with the financial charts toolbar.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgChartOptions,
AnimationModule,
AnnotationsModule,
CategoryAxisModule,
ChartToolbarModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
LineSeriesModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-enterprise";
import { getData } from "./data";
ModuleRegistry.registerModules([
AnimationModule,
AnnotationsModule,
CategoryAxisModule,
ChartToolbarModule,
CrosshairModule,
LegendModule,
LineSeriesModule,
NumberAxisModule,
ContextMenuModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgChartOptions>({
data: getData(),
title: {
text: "Monthly Sales Revenue",
},
footnote: {
text: "2024, values in $1000s",
},
series: [
{
type: "line",
xKey: "month",
yKey: "revenue",
interpolation: { type: "smooth" },
marker: {
enabled: false,
},
},
],
listeners: {
annotations: (event) => {
console.log(event);
},
},
annotations: {
enabled: true,
toolbar: {
buttons: [
{
icon: "delete",
value: "clear",
},
{
icon: "text-annotation",
value: "text-menu",
},
],
},
},
initialState: {
annotations: [
{
type: "comment",
x: { value: "Feb", groupPercentage: -0.2 },
y: 46,
text: "$45,000",
fontSize: 12,
},
{
type: "text",
x: { value: "Jun", groupPercentage: -0.2 },
y: 81,
text: "$80,000",
fontSize: 12,
},
{
type: "note",
x: "Sep",
y: 75,
text: "End of summer dip recovered",
fontSize: 12,
},
{
type: "callout",
start: { x: { value: "Dec", groupPercentage: -0.1 }, y: 107 },
end: { x: "Oct", y: 110 },
text: "$95,000",
fontSize: 12,
},
],
},
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
export function getData() {
return [
{ month: "Jan", revenue: 32 },
{ month: "Feb", revenue: 45 },
{ month: "Mar", revenue: 38 },
{ month: "Apr", revenue: 50 },
{ month: "May", revenue: 65 },
{ month: "Jun", revenue: 80 },
{ month: "Jul", revenue: 78 },
{ month: "Aug", revenue: 72 },
{ month: "Sep", revenue: 85 },
{ month: "Oct", revenue: 95 },
{ month: "Nov", revenue: 90 },
{ month: "Dec", revenue: 105 },
];
}
This event contains:
- The array of
annotations.
In this example:
- When an annotation is changed, added or removed, the event is output to the console.
zoom Copy Link
This is fired when the zoom level or position changes. This is triggered when zooming in or out of the chart, panning or using the Navigator.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgCartesianChartOptions,
AnimationModule,
CategoryAxisModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
LineSeriesModule,
ModuleRegistry,
NumberAxisModule,
ZoomModule,
} from "ag-charts-enterprise";
import { getData } from "./data";
ModuleRegistry.registerModules([
AnimationModule,
CategoryAxisModule,
CrosshairModule,
LegendModule,
LineSeriesModule,
NumberAxisModule,
ZoomModule,
ContextMenuModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgCartesianChartOptions>({
title: {
text: "2023 Average Temperatures",
},
subtitle: {
text: "Oxford, UK",
},
zoom: {
enabled: true,
anchorPointX: "pointer",
},
listeners: {
zoom: (event) => {
console.log(event);
},
},
data: getData(),
series: [
{
type: "line",
xKey: "month",
xName: "Month",
yKey: "min",
yName: "Min Temperature",
interpolation: { type: "smooth" },
},
{
type: "line",
xKey: "month",
xName: "Month",
yKey: "max",
yName: "Max Temperature",
interpolation: { type: "smooth" },
},
],
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
// Source: https://www.metoffice.gov.uk/pub/data/weather/uk/climate/stationdata/oxforddata.txt
export function getData() {
return [
{ month: "January", max: 8.5, min: 2.6 },
{ month: "February", max: 10.4, min: 3.0 },
{ month: "March", max: 10.9, min: 4.7 },
{ month: "April", max: 13.7, min: 5.0 },
{ month: "May", max: 18.2, min: 8.4 },
{ month: "June", max: 23.6, min: 12.2 },
{ month: "July", max: 21.3, min: 13.0 },
{ month: "August", max: 21.9, min: 13.1 },
{ month: "September", max: 22.6, min: 13.2 },
{ month: "October", max: 17.0, min: 9.7 },
{ month: "November", max: 11.1, min: 4.9 },
{ month: "December", max: 10.2, min: 5.2 },
];
}
This event contains:
- A
ratioXandratioYwithstartandendproperties with values between0and1. These represent a proportion of the width or height of the chart. - Any non-category axes also include
rangeXorrangeYproperties. These contain values that match the axis type, e.g. a date for an Ordinal Time Axis.
In this example:
- When the zoom level is changed or the chart is panned, the event is output to the console.
Series Events Copy Link
These are fired on click or double-click of the series node. Depending on the type of series, a node can mean a bar or a pie sector, or a marker, such as a Line or an Area series marker.
These events contain:
- The
seriesthe node belongs to. - The piece of chart data or
datum. - The specific keys in that
datumthat were used to fetch the values represented by the clicked node.
seriesNodeClick and seriesNodeDoubleClick Copy Link
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgChartOptions,
BarSeriesModule,
CategoryAxisModule,
LegendModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
import { DataType, getData } from "./data";
function makeMessage(header: string, datum: DataType) {
const { brands, month, units } = datum;
const buffer: string[] = [
header,
"\nCars sold in ",
month,
": ",
String(units),
"\n",
];
for (const key in brands) {
buffer.push(key, ": ", String(brands[key]), "\n");
}
return buffer.join("");
}
ModuleRegistry.registerModules([
BarSeriesModule,
CategoryAxisModule,
LegendModule,
NumberAxisModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgChartOptions<DataType>>({
title: {
text: "Number of Cars Sold",
},
subtitle: {
text: "(click a column for details)",
},
data: getData(),
series: [
{
type: "bar",
xKey: "month",
yKey: "units",
listeners: {
seriesNodeClick: (event) =>
console.log(makeMessage("[click]", event.datum)),
seriesNodeDoubleClick: (event) =>
console.log(makeMessage("[double click]", event.datum)),
},
},
],
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
export interface DataType {
month: string;
units: number;
brands: {
[key: string]: number;
};
}
export function getData(): DataType[] {
return [
{ month: "March", units: 25, brands: { BMW: 10, Toyota: 15 } },
{ month: "April", units: 27, brands: { Ford: 17, BMW: 10 } },
{ month: "May", units: 42, brands: { Nissan: 20, Toyota: 22 } },
];
}
In this example:
- Whenever a bar is clicked or double-clicked, information about that bar is shown in the console.
- The event listener pulls extra information from the datum containing the bar's value and shows it in the console as well. In this case the breakdown of sales numbers by brand name.
Legend Events Copy Link
legendItemClick and legendItemDoubleClick Copy Link
These are fired on click or double-click of a legend item.
These events contain:
- The
seriesIdof the series associated with the legend item. - The
itemId, usually theyKeyvalue for cartesian series.
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgCartesianChartOptions,
AgChartLegendClickEvent,
AgChartLegendDoubleClickEvent,
CategoryAxisModule,
LegendModule,
LineSeriesModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
ModuleRegistry.registerModules([
CategoryAxisModule,
LegendModule,
LineSeriesModule,
NumberAxisModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgCartesianChartOptions>({
data: [
{
quarter: "Q1",
petrol: 200,
diesel: 100,
},
{
quarter: "Q2",
petrol: 300,
diesel: 130,
},
{
quarter: "Q3",
petrol: 350,
diesel: 160,
},
{
quarter: "Q4",
petrol: 400,
diesel: 200,
},
],
series: [
{
type: "line",
xKey: "quarter",
yKey: "petrol",
},
{
type: "line",
xKey: "quarter",
yKey: "diesel",
},
],
legend: {
listeners: {
legendItemClick: ({ seriesId, itemId }: AgChartLegendClickEvent) => {
console.log(`Click - seriesId: ${seriesId}, itemId: ${itemId}`);
},
legendItemDoubleClick: ({
seriesId,
itemId,
}: AgChartLegendDoubleClickEvent) => {
console.log(
`Double Click - seriesId: ${seriesId}, itemId: ${itemId}`,
);
},
},
},
});
return <AgCharts options={options} />;
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
{
legend: {
listeners: {
legendItemClick: ({ seriesId, itemId }) => {
console.log(`seriesId: ${seriesId}, itemId: ${itemId}`);
},
},
},
}In this example:
- When a legend item is clicked, a message is logged to the console with the
legendItemClickevent contents. - When a legend item is double clicked, a message is logged to the console with the
legendItemDoubleClickevent contents.
Series Visibility Toggling Copy Link
Although clicking a legend item will usually toggle the series visibility, this is not included in the legend events. Use the chart seriesVisibilityChange event to listen for this.
The legend item click events include a preventDefault function that can be called to stop the default series visibility toggling. See the seriesVisibilityChange event documentation for an example of this.
Interaction Ranges Copy Link
By default, the seriesNodeClick event is only triggered when the user clicks exactly on a node. You can use the nodeClickRange option to instead define a range at which the event is triggered. This can be set to one of three values: 'nearest', 'exact' or a number as a distance in pixels.
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
AgCartesianChartOptions,
CategoryAxisModule,
LegendModule,
LineSeriesModule,
ModuleRegistry,
NumberAxisModule,
} from "ag-charts-community";
import { DataType, getData } from "./data";
import clone from "clone";
ModuleRegistry.registerModules([
CategoryAxisModule,
LegendModule,
LineSeriesModule,
NumberAxisModule,
]);
const ChartExample = () => {
const [options, setOptions] = useState<AgCartesianChartOptions<DataType>>({
data: getData(),
series: [
{
type: "line",
xKey: "quarter",
yKey: "petrol",
nodeClickRange: "exact",
listeners: {
seriesNodeClick: ({ datum }) =>
console.log(`petrol - ${datum.petrol}`),
},
},
{
type: "line",
xKey: "quarter",
yKey: "diesel",
nodeClickRange: "exact",
listeners: {
seriesNodeClick: ({ datum }) =>
console.log(`diesel - ${datum.diesel}`),
},
},
],
});
const exact = () => {
const nextOptions = clone(options);
nextOptions.series = nextOptions.series!.map((series) => ({
...series,
nodeClickRange: "exact",
}));
setOptions(nextOptions);
};
const nearest = () => {
const nextOptions = clone(options);
nextOptions.series = nextOptions.series!.map((series) => ({
...series,
nodeClickRange: "nearest",
}));
setOptions(nextOptions);
};
const distance = () => {
const nextOptions = clone(options);
nextOptions.series = nextOptions.series!.map((series) => ({
...series,
nodeClickRange: 10,
}));
setOptions(nextOptions);
};
return (
<Fragment>
<div className="example-controls">
<div className="controls-row">
<button onClick={exact}>Exact (Default)</button>
<button onClick={nearest}>Nearest</button>
<button onClick={distance}>Distance (10 Pixels)</button>
</div>
</div>
<AgCharts options={options} />
</Fragment>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(<ChartExample />);
export interface DataType {
quarter: string;
petrol: number;
diesel: number;
}
export function getData(): DataType[] {
return [
{
quarter: "Q1",
petrol: 200,
diesel: 100,
},
{
quarter: "Q2",
petrol: 300,
diesel: 130,
},
{
quarter: "Q3",
petrol: 350,
diesel: 160,
},
{
quarter: "Q4",
petrol: 400,
diesel: 200,
},
];
}
In this example:
'exact'(default) will trigger the event if the user clicks exactly on a node.'nearest'will trigger the event for whichever node is nearest to the click.- Given a number it will trigger the event when the click is made within that many pixels of a node.
Item Identifiers Copy Link
Many events expose an itemId to identify the item within its series. How it is derived depends on the item type:
- Series nodes use a node identifier.
- Automatically generated from the data, and may change when the data updates.
- Set
dataIdKeyto use adatumfield as a stable identifier across data updates (see Identifying Items by Key). - Series whose nodes don't map directly to a datum - such as Histogram bins and Sankey or Chord nodes - expose a
getItemIdcallback instead. - Waterfall
totalandsubtotalbars use theirtotals.itemIdif set, otherwise theirtotals.axisLabel.
- Legend items use the legend item's identifier. Typically the
yKeyvalue for most series, or the legend item's position for series with one legend item per datum, such aspieanddonut.
API Reference Copy Link
All series event options have similar interface contracts. See the series-specific documentation for variations.