Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

Dash Bootstrap Components - DropdownMenu Value

Hello,
I use the new module “Dash Bootstrap Components”. I would like to change the label of a “DropdownMenu” according to the choice made by the user. I’m trying to use an “@ app.callback” to retrieve the value chosen from the menu, but I do not see how to get it back.

Do you know how to do it?

thank you,

Gamejuel

You’ll probably find that the Dropdown in dash-core-components is better for this type of thing, however, if you really want to us DropdownMenu from dash-bootstrap-components it is possible using dash.callback_context (you need Dash version 0.38.0 or later for this feature). Here’s a simple example:

import dash
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.DropdownMenu(
    [
        dbc.DropdownMenuItem("Item 1", id="item-1"),
        dbc.DropdownMenuItem("Item 2", id="item-2"),
    ],
    label="Item 1",
    id="dropdownmenu",
)


@app.callback(
    Output("dropdownmenu", "label"),
    [Input("item-1", "n_clicks"), Input("item-2", "n_clicks")],
)
def update_label(n1, n2):
    # use a dictionary to map ids back to the desired label
    # makes more sense when there are lots of possible labels
    id_lookup = {"item-1": "Item 1", "item-2": "Item 2"}

    ctx = dash.callback_context

    if (n1 is None and n2 is None) or not ctx.triggered:
        # if neither button has been clicked, return "Not selected"
        return "Not selected"

    # this gets the id of the button that triggered the callback
    button_id = ctx.triggered[0]["prop_id"].split(".")[0]
    return id_lookup[button_id]


if __name__ == "__main__":
    app.run_server(debug=True)
1 Like

Thx tcbegley ! It’s works perfectly :slight_smile:
I prefer use DropdownMenu because of his beautiful style !

Thx a lot for the components !

On more question, how to do if my Dropdown list is dynamic ?
I can not declare the arguments n_clicks of the callback function.

Thx :slight_smile:

On more question, how to do if my Dropdown list is dynamic?

This may not be possible. As you suggest, you need to know the list of Inputs at the moment the callback is registered, and once the callback has been registered, I’m not aware that it’s possible to change this.

Ultimately the reason for this is that DropdownMenu is intended more as a static list of options, primarily for navigation, so the component isn’t that well equipped for large dynamic lists of options that the user should select from.

If you really like the look of it though, it may be possible to modify the style of the dash-core-components dropdown to look more like the DropdownMenu.

If you really like the look of it though, it may be possible to modify the style of the dash-core-components dropdown to look more like the DropdownMenu

I’m using the DARKLY bootstrap theme and I’d like the DCC Dropdown to look like the DARKLY DropdownMenu.
Do you know how to update the CSS style to match it?

Below is some CSS that you can add to your app and it should do what you want, just make sure you wrap the dropdown with an element that has the “dash-bootstrap” class applied like this:

app.layout = html.Div([dcc.Dropdown(...)], className="dash-bootstrap")

I took the CSS from here and made a few modifications to make it look more like the DropdownMenu. With the below CSS + Darkly I get something that looks like this

image

but you can play around with the styles to achieve whatever look you like.

.dash-bootstrap .Select-control {
  height: calc(1.5em + 0.75rem + 2px);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.5;
  color: #fff;
  background-color: #222;
  background-clip: padding-box;
  border: 1px solid #444;
  border-radius: 0.25rem;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

@media (prefers-reduced-motion: reduce) {
  .dash-bootstrap .Select-control {
    transition: none;
  }
}

.dash-bootstrap .Select-control:hover {
  box-shadow: none;
}

.dash-bootstrap .is-open > .Select-control {
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}

.dash-bootstrap .is-focused:not(.is-open) > .Select-control {
  border-color: #aaa;
  outline: 0;
  box-shadow: 0 0 0 0.2rem rgba(55, 90, 127, 0.25);
}

.dash-bootstrap .Select.is-disabled > .Select-control {
  background-color: #ebebeb;
}

.dash-bootstrap .Select--multi .Select-value {
  border-radius: 0.125rem;
  color: #eee;
  border-color: rgba(200, 200, 200, 0.25);
  background-color: rgba(55, 55, 55, 0.1);
}

.dash-bootstrap .Select--multi .Select-value-icon:hover {
    background-color: #333;
    color: #fff;
}

.dash-bootstrap .Select--multi .Select-value-icon {
  border-right-color: rgba(55, 55, 55, 0.25);
}

.dash-bootstrap .has-value.Select--single > .Select-control .Select-value .Select-value-label,
.dash-bootstrap .has-value.is-pseudo-focused.Select--single > .Select-control .Select-value .Select-value-label {
  color: #444;
}

.dash-bootstrap .Select-multi-value-wrapper {
  height: calc(1.5em + 0.75rem);
}

.dash-bootstrap .Select-placeholder {
  color: #999;
  padding-left: 0.75rem;
  padding-right: 0.75rem;
}

.dash-bootstrap .Select--single > .Select-control .Select-value,
.dash-bootstrap .Select-placeholder {
  line-height: calc(1.5em + 0.75rem);
}

.dash-bootstrap .Select-input {
  height: calc(1.5em + 0.75rem);
}

.dash-bootstrap .Select-menu-outer {
  border-bottom-right-radius: 0.25rem;
  border-bottom-left-radius: 0.25rem;
  background-color: #222;
  background-clip: padding-box;
  border: 1px solid #444;
  border-top-color: transparent;
  box-shadow: none;
  color: #fff;
}

.dash-bootstrap .VirtualizedSelectOption {
  height: calc(1.5em + 0.75rem) !important;
}

.dash-bootstrap .VirtualizedSelectFocusedOption {
  background-color: rgba(55, 90, 127, 0.1) !important;
}
2 Likes

Thank you very much tcbegley for taking the time to answer me :blush:. I managed to get the desired result.

1 Like

Where do I place the css code relative to the dash app? How does the className=“dash-bootstrap” find the css code?

The easiest way is to place the CSS files in a folder called assets in the same directory as your app.py file. Check out the Dash docs on external resources for more details.

Thanks! How do I get the background of the scatterplot to much up with the bootstrap SUPERHERO css?

You have to just fiddle around with the layout properties of the Plotly figure object you’re creating. You can find out the color codes Superhero is using by looking at the uncompiled SCSS, or the compiled CSS.

Here’s a little demo I just tried out. For the plot background color there wasn’t an obvious choice, so I chose white with 10% opacity which has the effect of slightly lightening the background color.

import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import plotly.graph_objs as go

data = [
    go.Scatter(
        x=[1, 2, 3, 4, 5], y=[4, 1, 2, 5, 2], marker={"color": "#DF691A"}
    )
]

layout = {
    "paper_bgcolor": "#2B3E50",
    "plot_bgcolor": "rgba(1.0, 1.0, 1.0, 0.1)",
    "title": "A superhero plot",
    "titlefont": {"color": "#FFF"},
    "xaxis": {"tickfont": {"color": "#FFF"}},
    "yaxis": {"tickfont": {"color": "#FFF"}},
}

fig = go.Figure(data=data, layout=layout)

app = dash.Dash(external_stylesheets=[dbc.themes.SUPERHERO])

app.layout = dbc.Container(dcc.Graph(figure=fig), className="p-5")

if __name__ == "__main__":
    app.run_server(debug=True)

Hey!! How would you do the same thing for “dash-core-components”?