Dropdowns to create interactive graphs not working

I’ve been trying to get this dropdown working for weeks with no success, What am I doing wrong?

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import Macro

app = dash.Dash(name,)

app.layout = html.Div([

html.Label('Dropdown'),
dcc.Dropdown(
    id='Dropdown_1',
    options=[
        {'label': 'US Index', 'value': Macro.US_Macro},
        {'label': 'EU Index', 'value': Macro.EU_Macro},
    ],
    value = Macro.US_Macro,
    multi = True
),


html.H1(
    children='Global Economies',
    style={
        'textAlign': 'center',
        'color': '#7FDBFF'
    }
),


dcc.Graph(id='Graph1'),

])

@app.callback(
Output(component_id=‘Graph1’, component_property=‘figure’),
[Input(component_id=‘Dropdown_1’, component_property= ‘value’)]
)
def update_graph(input_value):

return {
    'data': [
        go.Scatter(
            x = input_value['x'],
            y = input_value['y'],
            mode='lines',
            name= input_value['name'],
            marker = input_value['marker']
        )
    ],
    'layout': go.Layout(
        dragmode='pan', 
    )
}     

if name == ‘main’:
app.run_server(debug=True)

Code from Macro.py which the above code is referencing:

US_Macro = {‘x’: US.index, ‘y’: US, ‘name’: ‘United States’, ‘marker’: {‘color’: ‘lime’}}
EU_Macro = {‘x’: EU.index, ‘y’: EU, ‘name’: ‘European Union’, ‘marker’: {‘color’: ‘blue’}}

where US and EU are pandas dataframes.

always I get invalid value passed to dropdown error, and the dropdown doesn’t even load.

The value can only be a string or a number, not an arbitrary object. Typical approaches for your use case are,

  1. Serialize your object to a string, and deserialize it in the callback.
  2. Store the objects somewhere (in memory, in a file, etc.) where they can be looked up via a key. Use the key as value in the drop down and lookup the object in the callback.

Thank you, that definitely got me further. I added a dictionary of values and keys called all_options , and referenced the string values in the dropdown and pass those into the callback.
My function in the callback now looks like:

def update_graph(input_value):

return {
    'data': [
        go.Scatter(
            x = all_options[input_value]['x'],
            y = all_options[input_value]['y'],
            mode='lines',
            name= all_options[input_value]['name'],
            marker = all_options[input_value]['marker']
        )
    ],
    'layout': go.Layout(
        dragmode='pan', 
    )
}    

When I start the app, I get the dropdown to show up as well as the first plot with no errors, though when I try to edit the graph in any way from the dropdown, then I get:

TypeError: unhashable type: ‘list’

Traceback (most recent call last)
File “/home/jsgart/VSCode/Macro Indicator/app.py”, line 58, in update_graph
x = all_options[input_value][‘x’],
TypeError: unhashable type: ‘list’
Traceback (most recent call last):
File “/home/jsgart/VSCode/Macro Indicator/app.py”, line 58, in update_graph
x = all_options[input_value][‘x’],
TypeError: unhashable type: ‘list’

Upon inspection it looks like even though I have one initial value set, that all the values of the dropdown are trying to get passed in at once? I am guessing this is normal behavior and that I now need to process these values in a for loop?

Got it! Modified the function in the callback to:

def update_graph(input_value):
traces =
selected_plot = input_value

for input_value in selected_plot:
    traces.append(dict(
        x = all_options[input_value]['x'],
        y = all_options[input_value]['y'],
        mode='lines',
        name= all_options[input_value]['name'],
        marker = all_options[input_value]['marker']
    ))

return {
    'data': traces,
    'layout': go.Layout(
        dragmode='pan', 
    )
}    

Thank you Emil, for responding so fast after my initial post and pointing me in the right direction! I’ve been wrestling with this first Dash app of mine for weeks!

1 Like