0
votes

I have two callbacks from dropdown menus which should lead to a datatable. There is a database consisting of an entry code, a car type, and it’s year. The dropdown menu will allow you to choose the car, and then the year, and the resulting datatable should be a listing of all of the chosen cars and all cars newer than the year chosen.

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)

dataa = [[‘ABQ’,‘Toyota’,2015],[‘QRC’,‘Honda’,2016],[‘BFG’,‘Honda’,2017],[‘AAA’,‘Toyota’,2018],[‘KLX’,‘Toyota’,2020]]
dframe = pd.DataFrame(dataa,columns=[‘Entry’,‘Car’, ‘Year’])

app.layout = html.Div([

html.Label("Name:", style={'fontSize':70, 'textAlign':'center'}),

dcc.Dropdown(
    id='cars-dpdn',
    options=[{'label': s, 'value': s} for s in sorted(dframe.Car.unique())],

    clearable=False
),

html.Label("Year", style={'fontSize':30, 'textAlign':'center'}),
dcc.Dropdown(
    id='years-dpdn', 
    options=[],
),

html.Label("Results:", style={'fontSize':70, 'textAlign':'center'}),

html.Div(id="table1")
])

@app.callback(
Output(‘years-dpdn’, ‘options’),
Input(‘cars-dpdn’, ‘value’)
)
def years(chosen_car):
dff = dframe[dframe.Car==chosen_car]
return [{‘label’: c, ‘value’: c} for c in sorted(dff.Year.unique())]

@app.callback(
Output(‘years-dpdn’, ‘value’),
Input(‘years-dpdn’, ‘options’)
)
def years_value(available_options):
return [x[‘value’] for x in available_options]

@app.callback(
Output(‘table1’, ‘figure’),
Input(‘cars-dpdn’, ‘value’),
Input(‘years-dpdn’, ‘value’),
)

def update_table(car, year):

dfa = dframe[dframe['Car']==car]
dfb = dfa[dfa['Year']>year]

return html.Div([dash_table.DataTable(
    data=dfb.to_dict('rows'),
    columns=[{'name': i, 'id': i} for i in dfb.columns],
    ),
    html.Hr()
                ])
if name == ‘main’:
app.run_server(debug=False, port = 3060)

The dropdown menus function correctly, allowing me to choose the Car and Year value, however there is no table that is created. It is just blank. The error message is longwinded, but here is the ending:

ValueError: Lengths must match to compare

127.0.0.1 - - [30/Dec/2020 20:45:00] “POST /_dash-update-component HTTP/1.1” 500 - 
127.0.0.1 - - [30/Dec/2020 20:45:00] “POST /_dash-update-component HTTP/1.1” 200 - 
127.0.0.1 - - [30/Dec/2020 20:45:02] “POST /_dash-update-component HTTP/1.1” 200 -
1

1 Answers

0
votes

It would help to have the full traceback of the error if you can share that. There is an issue with how you've defined your callbacks. The Inputs should all be wrapped in square brackets. For example, you have:

@app.callback(
    Output(‘table1’, ‘figure’),
    Input(‘cars-dpdn’, ‘value’),
    Input(‘years-dpdn’, ‘value’),
)

but it should be:

@app.callback(
    Output(‘table1’, ‘figure’),
    [
      Input(‘cars-dpdn’, ‘value’),
      Input(‘years-dpdn’, ‘value’),
    ]
)

This must be the case even if there is only one Input. Otherwise Dash will throw errors.

This callback also looks suspect:

@app.callback(
    Output(‘years-dpdn’, ‘value’),
    Input(‘years-dpdn’, ‘options’)
)
def years_value(available_options):
    return [x[‘value’] for x in available_options]

You're outputing to the dropdown's value prop, but that prop won't accept a list, so you should give it just a single item from the list you've created.