Search code examples
pythonhtmlcssplotly-dashdashboard

Dash: Fit a dropdown and graph in an inline-block


I want to plot 4 graphs side-by-side in the style of a 2x2 grid. The graph in the lower right corner I want to attach a dropdown to with a callback that allows for changing the color.

I have an example of it below. However, the issue is that I have to explicitly set the width, otherwise the graph wont display. Am I doing this correctly?

from dash import Dash, dcc, html, Input, Output
import plotly.graph_objects as go

app = Dash(__name__)


f1 = go.Figure(go.Bar(x=["a", "b", "c"], y=[2, 3, 1], marker_color="Gold"))
f2 = go.Figure(go.Bar(x=["a", "b", "c"], y=[2, 3, 1], marker_color="Gold"))
f3 = go.Figure(go.Bar(x=["a", "b", "c"], y=[2, 3, 1], marker_color="Gold"))
f4 = go.Figure(go.Bar(x=["a", "b", "c"], y=[2, 3, 1], marker_color="Gold"))


app.layout = html.Div([
        html.Div([dcc.Graph(id="1", figure=f1)], style={'display': 'inline-block'}),
        html.Div([dcc.Graph(id="2", figure=f2)], style={'display': 'inline-block'}),
        html.Div([dcc.Graph(id="3", figure=f3)], style={'width': '37%', 'display': 'inline-block'}),
        html.Div([
        dcc.Dropdown(
            id="dropdown",
            options=["Gold", "MediumTurquoise", "LightGreen"],
            value="Gold",
            clearable=False), dcc.Graph(id="4", figure=f4)], style={'width': '37%', 'display': 'inline-block'})])
    

@app.callback(
    Output("4", "figure"),
    Input("dropdown", "value"),
)
def display_color(color):
    fig = go.Figure(go.Bar(x=["a", "b", "c"], y=[2, 3, 1], marker_color=color))
    return fig


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

Solution

  • This is mainly a HTML/CSS problem. I'm not an expert here but you could create a simple "grid" by wrapping every row with an html.Div and styling the elements (columns) via {'width': '50%', 'display': 'inline-block'}. For the second row, second column, you have to wrap the dropdown and the graph into an additional html.Div which gets the 50% width.

    Here is the code for the layout:

    block_column_50_style = {'width': '50%', 'display': 'inline-block'}
    
    app.layout = html.Div([
        html.Div(
            [
                dcc.Graph(id="1", figure=f1, style=block_column_50_style),
                dcc.Graph(id="2", figure=f2, style=block_column_50_style)
            ]
        ),
        html.Div(
            [
                dcc.Graph(id="3", figure=f3, style=block_column_50_style),
                html.Div(
                    [
                        dcc.Dropdown(
                            id="dropdown",
                            options=["Gold", "MediumTurquoise", "LightGreen"],
                            value="Gold",
                            clearable=False),
                        dcc.Graph(id="4", figure=f4)
                    ],
                    style=block_column_50_style
                )
            ]
        )
    ])
    

    And a screenshot of the page:

    enter image description here

    P.S. If you don't want to create this grid yourself, I can recommend using Dash Bootstrap Components which has an API for using Bootstrap's grid layout. This will make it easier :)