Issue with 'new_dropdown'
Ypsingh18 opened this issue · comments
I am currently on a web-app which involves using the new_dropdown element however I am having a hard time figuring out how enable multi selection. I am used to being able to just call 'multi = True', however, when i try that i get the following "TypeError: new_dropdown() got an unexpected keyword argument 'multi'", please let me know if there is another way to enable multi selection. Thanks!
Hi @Ypsingh18
The helper functionnew_dropdown()
has certain common props defined as keyword arguments, and the others can be included using the opts
keyword.
For example, if you are using a template that is not a dash-bootstrap-components
template, you can include the multi=True
like this:
continent=tpl.new_dropdown(continents, value=continents, label="Continents", opts={"multi": True}),
For context, here it is in a complete MWE:
import dash
import dash_labs as dl
import plotly.express as px
import plotly.graph_objects as go
# Make app and template
app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()])
tpl = dl.templates.FlatDiv(app)
# Load and preprocess dataset
df = px.data.gapminder()
years = sorted(df.year.drop_duplicates())
continents = list(df.continent.drop_duplicates())
@app.callback(
args=dict(
year=tpl.new_slider(
years[0], years[-1], step=5, value=years[-1], label="Year"
),
continent=tpl.new_dropdown(continents, value=continents, label="Continents", opts={"multi": True}),
logs=tpl.new_checklist(
["log(x)"], value="log(x)", label="Axis Scale",
),
),
output=tpl.new_graph(),
template=tpl,
)
def callback(year, continent, logs):
# Let parameterize infer output component
year_df = df[df.year == year]
if continent:
year_df = year_df[year_df.continent.isin(continent)]
if not len(year_df):
return go.Figure()
title = f"Life Expectancy ({year})"
return px.scatter(
year_df,
x="gdpPercap",
y="lifeExp",
size="pop",
color="continent",
hover_name="country",
log_x="log(x)" in logs,
size_max=60,
title=title
).update_layout(
margin=dict(l=0, r=0, b=0)
).update_traces(marker_opacity=0.8)
app.layout = tpl.children
if __name__ == "__main__":
app.run_server(debug=True)
However, if you are using a dash-bootstrap-components
template (such as DbcSidebar
, etc) then the new_dropdown()
function uses dbc.Select()
as the dropdown component. Unfortunately, dbc.Select()
does not support multiple selections and does not have a multi
prop.
You can use a dcc.Dropdown
with a bootstrap template - it just needs to be included without using the new_dropdown()
helper function. Here is an example app to demonstrate:
import dash
import dash_labs as dl
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import plotly.express as px
import plotly.graph_objects as go
# Make app and template
app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()])
tpl = dl.templates.DbcCard(app, "Gapminder", figure_template=True)
# Load and preprocess dataset
df = px.data.gapminder()
years = sorted(df.year.drop_duplicates())
continents = list(df.continent.drop_duplicates())
multi_dropdown = dcc.Dropdown(
options=[{"label": c, "value": c} for c in continents], value=continents, multi=True
)
@app.callback(
args=dict(
year=tpl.new_slider(years[0], years[-1], step=5, value=years[-1], label="Year"),
continent=dl.Input(multi_dropdown, label="Continents"),
logs=tpl.new_checklist(
["log(x)"],
value="log(x)",
label="Axis Scale",
),
),
output=tpl.new_graph(),
template=tpl,
)
def callback(year, continent, logs):
# Let parameterize infer output component
year_df = df[df.year == year]
if continent:
year_df = year_df[year_df.continent.isin(continent)]
if not len(year_df):
return go.Figure()
title = f"Life Expectancy ({year})"
return (
px.scatter(
year_df,
x="gdpPercap",
y="lifeExp",
size="pop",
color="continent",
hover_name="country",
log_x="log(x)" in logs,
size_max=60,
title=title,
)
.update_layout(margin=dict(l=0, r=0, b=0))
.update_traces(marker_opacity=0.8)
)
app.layout = dbc.Container(fluid=True, children=tpl.children)
if __name__ == "__main__":
app.run_server(debug=True)
Oh wow thank you for the wonderful explanation on how to get around this issue! Using the second method worked perfectly!