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

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.