plotly / dash-labs

Work-in-progress technical previews of potential future Dash features.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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!