Hi Dash Community,
I’m trying to add interactivity to my dashboard following the code examples given here: (https://dash.plot.ly/interactive-graphing). In the “Update Graphs on Hover” section the callbacks use this syntax to grab custom data defined in the figure for a callback update, country_name = hoverData[‘points’][0][‘customdata’]. I’m trying to adapt this for use in clickData using the same syntax. However, I keep getting a type error that says: “TypeError: string indices must be integers”. To me that would indicate that after [‘points’] all further sub-indexing would have to be integers. But that’s not the way the example code is doing things. Without being able to access that ‘customdata’ property I can’t update my figure properly. Best I can come up with is that there something about the ‘customdata’ property that I’m not using properly. But I haven’t been able to find any documentation to validate that hunch. Thoughts? Any assistance would be greatly appreciated.
-cyranothebard
Hi @cyranothebard, below is the code of the callbacks adapted for clickData
. I had to test whether clickData
is None
and in this case return dash.no_update
, otherwise I also had indexing problems (because None
cannot be indexed). I hope the code below also works for you
@app.callback(
dash.dependencies.Output('x-time-series', 'figure'),
[dash.dependencies.Input('crossfilter-indicator-scatter', 'clickData'),
dash.dependencies.Input('crossfilter-xaxis-column', 'value'),
dash.dependencies.Input('crossfilter-xaxis-type', 'value')])
def update_y_timeseries(clickData, xaxis_column_name, axis_type):
if not clickData:
return dash.no_update
country_name = clickData['points'][0]['customdata']
dff = df[df['Country Name'] == country_name]
dff = dff[dff['Indicator Name'] == xaxis_column_name]
title = '<b>{}</b><br>{}'.format(country_name, xaxis_column_name)
return create_time_series(dff, axis_type, title)
@app.callback(
dash.dependencies.Output('y-time-series', 'figure'),
[dash.dependencies.Input('crossfilter-indicator-scatter', 'clickData'),
dash.dependencies.Input('crossfilter-yaxis-column', 'value'),
dash.dependencies.Input('crossfilter-yaxis-type', 'value')])
def update_x_timeseries(clickData, yaxis_column_name, axis_type):
if not clickData:
return dash.no_update
dff = df[df['Country Name'] == clickData['points'][0]['customdata']]
dff = dff[dff['Indicator Name'] == yaxis_column_name]
return create_time_series(dff, axis_type, yaxis_column_name)
Hi @Emmanuelle!
Thanks for responding. I appreciate your suggestion about the dash.no_update needing to be added. That makes a lot of sense and I’ve adjusted my update function to reflect that. However, I believe I’ve got a more fundamental issue that must be resolved first. My customdata is a string, a label for one of the series in my stacked bar plot. I’ve currently got a json dump attached to my graph to show the results of my clickData to help troubleshoot. It seems my customdata string is being indexed by PointNumber or PointIndex. I can’t troubleshoot my update function if the input to that function isn’t properly formatted. I’ve included screenshots of my dashboard and the relevant functions below. If I can disconnect my customdata formatting from PointNumber/PointIndex and get the indexing to work then I think I’ll be able to get the update functions working. Maybe I’m missing something about the nature of customdata indexing behavior or something…Thanks again for your help!
I don’t think the problem is with customdata
, but with clickData['points']['x']
: you need clickData['points'][0]['x']
instead. Don’t hesitate to add a lot of print statements to debug this kind of problems :-).
Ok. But I still have to make sure the string is getting passed properly from customdata
. Currently it’s still getting split up only returning the letter at the index given by pointNumber
/pointIndex
as shown in the top pic in the json. Do you know if there’s a connection between those keys that I can disable or if maybe I need to change the format of my customdata
value?