✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🐇 Announcing Dash VTK for 3d simulation graphics. Check out the March webinar.

On_click() function can't differ traces

Hi, everyone! I am trying to call print() function when points related to trace1 are being clicked. But for some reason callback function still triggers when I click on points related to trace2. What am I doing wrong? And is there a solution to replace on_click() function’s multiply calls (one call for one trace) with one?

f = go.FigureWidget(make_subplots(rows=2, cols=1))

trace1 = go.Scatter(x=[3, 4, 5], y=[10, 11, 12])
trace2 = go.Scatter(x=[6, 7, 8], y=[13, 14, 15])

f.add_trace(trace1, row=1, col=1)
f.add_trace(trace2, row=2, col=1)

def test(trace, points, selector):
    print("ayaya")
    
scatter = f.data[0]
scatter.on_click(test)
f

Hi @masterino,

With a slight modification it works. You have to iterate over figure traces, and print “ayaya” only if the clicked point is in the trace 0:

from plotly.subplots import make_subplots
f = go.FigureWidget(make_subplots(rows=2, cols=1))

trace1 = go.Scatter(x=[3, 4, 5], y=[10, 11, 12], name='trae1')
trace2 = go.Scatter(x=[6, 7, 8], y=[13, 14, 15])

f.add_trace(trace1, row=1, col=1)
f.add_trace(trace2, row=2, col=1)

def test(trace, points, state):
     if points.point_inds and points.trace_index == 0:
   
         print("ayaya")
    
for trace in f.data:
    trace.on_click(test)
f

There is no need to add on_click to every traces. Furthermore, it will call test as many time as there are traces if you do so (can be observed by putting a print(points.trace_name) inside test).

By adding the on_click only on the wanted trace, test will still be called whenever a data point is clicked (from any trace), but only once, and then the only check needed is for the points.point_inds to be non-empty, indicating that it is actually a data point from the selected trace that was clicked.

import plotly.graph_objects as go
from plotly.subplots import make_subplots

f = go.FigureWidget(make_subplots(rows=2, cols=1))

trace1 = go.Scatter(x=[3, 4, 5], y=[10, 11, 12], name='trace1')
trace2 = go.Scatter(x=[6, 7, 8], y=[13, 14, 15], name='trace2')

f.add_trace(trace1, row=1, col=1)
f.add_trace(trace2, row=2, col=1)

def test(trace, points, state):    
    # Skip when no point was actually clicked
    if not points.point_inds:
        return
    print('ayaya')

f.data[0].on_click(test)
f
1 Like