2
votes

I am trying to build a dashboard where the graph updates depending on the value passed in the dropdown menu.

For some reason, the graph does not adapt to any changes in the dropdown. Peculiarities about this are:

  1. The input is for sure received: I created a second function which has the same structure but updates a different field. It works fine.

  2. The problem seems to be with the graph display: I created a different version of the function where the update function would return "none" for the default value of 1. The area of the graph was empty at first but would change to one of the graphs when a new value was selected in the dropdown. Once a graph was shown, the field would not react to any further changes in the dropdown menu: Neither for values prompting a new graph nor for the return to the default value returning none.

This is the code:

import dash
from dash.dependencies import Output, Event
import dash_core_components as dcc
import dash_html_components as html
import plotly
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import collections


app = dash.Dash()

df = dm.return_all_pd_data(token = API_TOKEN)

app.layout = html.Div(children=[
    html.H1(children='''
        Month for graph:
    '''),
    dcc.Dropdown(
        id = "input",
        options=[
            {'label': 'Jan', 'value': 1},
            {'label': 'Feb', 'value': 2},
            {'label': 'Mar', 'value': 3}
        ], value = 1
    ),
    html.Div(id='output-graph'),
])

@app.callback(
    Output(component_id='output-graph', component_property='children'),
    [Input(component_id='input', component_property='value')])
def update_value(value):

    start = datetime.datetime(2018, value, 1, 0, 0, 0, 1)
    end = datetime.datetime(2018,  value + 1, 1, 0, 0, 0, 1)
    subset_df = df[ (df["lost_time"] > start) & (df["lost_time"] < end) ]

    x = pd.value_counts(subset_df.deal_source).index
    y = pd.value_counts(subset_df.deal_source).values

    return(dcc.Graph(
        id='output-graph',
        figure={
            'data': [
                {'x': x, 'y': y, 'type': 'bar', 'name': value},
            ],
            'layout': {
                'title': "You selected month: {}".format(value)
            }
        }
    ))


if __name__ == "__main__":

    app.run_server(debug = True)
1

1 Answers

3
votes

I was able to find the solution myself eventually. Answering here in case somebody else might have the same problem.

The problem was that I was trying to update the children element in the div tag. Instead it proved much easier to create an empty chart and write the function to update the figure element of the chart.

Below is the code which turned out to work:

app = dash.Dash()

app.layout = html.Div(children=[
    html.H1(children='''
        Interactive Chart:
    '''),
    dcc.Dropdown(
        id = "input",
        options=[
            {'label': 'January', 'value': 1},
            {'label': 'Febuary', 'value': 2},
            {'label': 'March', 'value': 3}
        ], value = 1
    ),
    dcc.Graph( id="output-graph")
])

@app.callback(
    Output(component_id='output-graph', component_property='figure'),
    [Input(component_id='input', component_property='value')])
def update_value(value):

    start = datetime.datetime(2018, value, 1, 0, 0, 0, 1)
    end = datetime.datetime(2018,  value + 1, 1, 0, 0, 0, 1)
    subset_df = df[ (df["lost_time"] > start) & (df["lost_time"] < end) ]
    x = pd.value_counts(subset_df.deal_source).index
    y = pd.value_counts(subset_df.deal_source).values

    return({'data': [
                {'x': x, 'y': y, 'type': 'bar', 'name': value},
            ],
            'layout': {
                'title': "Deal Flow source for {} 2018".format(months[value-1])
            }
        }
    )

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