Events
ApexCharts fires DOM-style events during user interaction and lifecycle phases, letting you attach your own handlers to build tooltips, drill-downs, linked charts, and other interactive behaviours.
The following events are available on the chart instance
- animationEnd
- beforeMount
- mounted
- updated
- mouseMove
- mouseLeave
- click
- legendClick
- markerClick
- xAxisLabelClick
- selection
- dataPointSelection
- dataPointMouseEnter
- dataPointMouseLeave
- beforeZoom
- beforeResetZoom
- zoomed
- scrolled
- brushScrolled
To know more about events, please refer to chart.events configuration
Handler signature
Every chart event handler receives the same three arguments:
function handler(event, chartContext, config) {
// event — the native MouseEvent (or null for lifecycle events)
// chartContext — the ApexCharts instance that fired the event
// config — { seriesIndex, dataPointIndex, config: chartOptions }
}
seriesIndex and dataPointIndex are -1 when the interaction is not over a specific data point (for example, a click on the chart background).
Common event patterns
dataPointMouseEnter
dataPointMouseEnter fires whenever the pointer moves over a data point marker or bar. Use it to read which series and point is hovered and to retrieve the underlying x/y values.
Config style (declared at chart creation time):
const options = {
chart: {
type: 'line',
events: {
dataPointMouseEnter: function (event, chartContext, config) {
const seriesIndex = config.seriesIndex // 0-based series index
const dataPointIndex = config.dataPointIndex // 0-based point index
const series = config.config.series
const xValue = series[seriesIndex].data[dataPointIndex].x
const yValue = series[seriesIndex].data[dataPointIndex].y
console.log(`Hovering series ${seriesIndex}, point ${dataPointIndex}`)
console.log(`x: ${xValue}, y: ${yValue}`)
}
}
},
series: [
{
name: 'Revenue',
data: [
{ x: 'Jan', y: 4200 },
{ x: 'Feb', y: 5800 },
{ x: 'Mar', y: 3900 }
]
}
],
xaxis: { type: 'category' }
}
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
Imperative style (attached after render):
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
chart.addEventListener('dataPointMouseEnter', function (event, chartContext, config) {
const seriesIndex = config.seriesIndex
const dataPointIndex = config.dataPointIndex
console.log(`Series ${seriesIndex}, point ${dataPointIndex}`)
})
Both styles are equivalent. The config style is convenient when setting up a chart from scratch; the imperative style is useful when you need to attach or swap handlers after the chart already exists.
click
click fires on any mouse click within the chart area. When the click lands on a data point, config.dataPointIndex is the zero-based index of that point in the series; when the click lands on the background, dataPointIndex is -1.
const options = {
chart: {
type: 'bar',
events: {
click: function (event, chartContext, config) {
if (config.dataPointIndex === -1) {
// click was on the chart background, not a bar
return
}
const seriesIndex = config.seriesIndex
const dataPointIndex = config.dataPointIndex
const clickedValue = config.config.series[seriesIndex].data[dataPointIndex]
console.log(`Clicked bar at series ${seriesIndex}, index ${dataPointIndex}`)
console.log('Value:', clickedValue)
}
}
},
series: [
{
name: 'Sales',
data: [30, 45, 22, 67, 53]
}
],
xaxis: {
categories: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
}
}
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
zoomed
zoomed fires after the user completes a drag-to-zoom gesture. The config object contains an xaxis property with min and max values describing the visible range after the zoom.
const options = {
chart: {
type: 'line',
zoom: {
enabled: true,
type: 'x'
},
events: {
zoomed: function (chartContext, { xaxis }) {
// xaxis.min and xaxis.max are timestamps (ms) when the x-axis is datetime,
// or category index numbers when the x-axis is category.
console.log('Zoomed range:')
console.log(' min:', new Date(xaxis.min).toISOString())
console.log(' max:', new Date(xaxis.max).toISOString())
}
}
},
series: [
{
name: 'Visits',
data: [
[new Date('2024-01-01').getTime(), 120],
[new Date('2024-02-01').getTime(), 340],
[new Date('2024-03-01').getTime(), 210],
[new Date('2024-04-01').getTime(), 480],
[new Date('2024-05-01').getTime(), 390]
]
}
],
xaxis: { type: 'datetime' }
}
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
Note: the second argument to zoomed is the raw config object, not the three-argument (event, chartContext, config) shape used by pointer events. Destructure { xaxis } directly from the second argument.
Subscribing imperatively (after render)
Use chart.addEventListener(name, handler) to attach a handler at any point after the chart has rendered, and chart.removeEventListener(name, handler) to detach it later. This is useful in framework components where you need to clean up on unmount.
const chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()
// Attach
function onHover(event, chartContext, config) {
console.log('Hovered point index:', config.dataPointIndex)
}
chart.addEventListener('dataPointMouseEnter', onHover)
// Detach (for example, on component unmount)
chart.removeEventListener('dataPointMouseEnter', onHover)
To remove a listener you must pass the same function reference that was used when adding it. Anonymous functions cannot be removed, so store the handler in a variable when you intend to clean it up later.