2025, Nov 08 03:00
Handling plotly_click in NiceGUI: extract the clicked point index from e.args and use it in Python
Learn how to handle Plotly clicks in NiceGUI: read GenericEventArguments, get e.args['points'][0]['pointIndex'], fix handlers, and persist the value in Python.
Handling user interaction in a NiceGUI + Plotly chart often starts with a simple question: how do you grab the clicked point and use it in Python, not just show a toast? The built-in example with ui.notify is great for smoke testing the event, but the next step is assigning the clicked index to a variable and acting on it. Let’s walk through exactly why a naive handler might fail and how to correctly extract the point index from the event payload.
Reproducing the issue
Consider a minimal setup where you attach a click handler to a Plotly figure but don’t accept any arguments in the handler and call notify without a message. It may look straightforward, but it won’t behave as intended.
import plotly.graph_objects as go
from nicegui import ui
def on_click_bad():
ui.notify()
chart_fig = go.Figure(go.Scatter(x=[1, 2, 3, 4], y=[1, 2, 3, 2.5]))
chart_fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
plot_area = ui.plotly(chart_fig).classes('w-full h-40')
plot_area.on('plotly_click', on_click_bad)
ui.run()What’s actually going wrong
The click binding is correct, but two details block the desired outcome. First, the handler for a Plotly interaction receives a single argument, the event object, and you need to accept it to access any payload. Second, notify without a message is not valid usage; it should be called with a string. There’s also a behavioral nuance: Plotly will emit the event only when you click a rendered point or element of the plot, not anywhere in empty space.
The event delivered by plotly_click is a GenericEventArguments instance. Its payload is available via the e.args dictionary, which holds the details you need. The index of the clicked point is located at e.args['points'][0]['pointIndex'].
The fix: extract indices from the event
Define the handler to accept the event and read the index from its args. If you want to keep the information around for later use, store it in a module-level variable as is common in GUI code, or act on it directly in the handler.
import plotly.graph_objects as go
from nicegui import ui
selected_point_idx = None
def on_point_click(evt):
global selected_point_idx
selected_point_idx = evt.args['points'][0]['pointIndex']
ui.notify(f'Clicked index: {selected_point_idx}')
plot_obj = go.Figure(go.Scatter(x=[1, 2, 3, 4], y=[1, 2, 3, 2.5]))
plot_obj.update_layout(margin=dict(l=0, r=0, t=0, b=0))
ui.plotly(plot_obj).classes('w-full h-40').on('plotly_click', on_point_click)
ui.run()This handler reads the point index straight from the event payload and assigns it to a Python variable. The notify call demonstrates that everything is wired correctly and also respects the requirement that notify is called with a message.
How to quickly inspect what the event sends
When connecting a handler for the first time, it helps to print whatever the event delivers so you can confirm the structure. That’s a quick way to discover available keys in e.args and verify that the event actually fires.
def inspect_event(*args, **kwargs):
print(args, kwargs)
# attach it temporarily
# ui.plotly(plot_obj).on('plotly_click', inspect_event)With this, you can see what arrives and then narrow down to the exact information you need.
Why this matters
Event handlers are the glue between a Plotly front end and NiceGUI’s Python-side state. If the handler signature is off or you ignore the payload, you lose the ability to react meaningfully to user actions. Understanding that plotly_click yields GenericEventArguments and that its data sits in e.args lets you build interactive behaviors reliably, from capturing a clicked index to triggering subsequent UI updates.
Takeaways
Always accept the event object in your handler so you can read e.args. Use e.args['points'][0]['pointIndex'] to obtain the clicked point index. Call ui.notify with a string if you want on-screen confirmation. Remember that plotly_click is emitted when clicking a plot element. And if you need the value elsewhere, store it in a variable that persists beyond the handler’s scope.