✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

dcc.Graph component not updating when callback with Inputs and State is fired

Hi community,

I’m building a simple dash app which retrieves data from an API (time series data) and displays it in a scatter plot. Here is a reduced example of what I’m trying to do:

   # App layout
   ######################################################################################

   app.layout = html.Div([
       html.Div([
           html.Div([
               # first dropdown
               html.Div([
                   dcc.Dropdown(
                       id='id-dropdown1',
                       options=[{'label': k, 'value': v} for k,v in dict1.items()],
                       placeholder="Select a value",
                       value="all"
                   )
               ],
               style={'width': '25%', 'display': 'inline-block', 'marginTop': 25}),

               # second dropdown
               html.Div([
                   dcc.Dropdown(
                       id='id-dropdown2',
                       placeholder="Select a value",
                       value="all"
                   )
               ],
               style={'width': '25%', 'display': 'inline-block', 'marginTop': 25}),

               # button
               html.Div([
                   html.Button(id='submit-button', n_clicks=0, children='Submit')],
                   style={'width':'25%', 'display':'inline-block', 'marginTop':25, 'float':'right'})
           ]),
       ]),

       # graph to update
       dcc.Graph(id='main-graph',style={'height':'550px'}),
   ])


   ######################################################################################
   # Reactive interactions between dropdown selections
   ######################################################################################

   @app.callback(
       dash.dependencies.Output('id-dropdown2', 'options'),
       [dash.dependencies.Input('id-dropdown1', 'value')])
   def dropdown2_update_1(dd1_value):
       # update options of dropdown2 depending on value of dropdown1
       return [{"label":label, "value":value} for label,value in somedict.items()]

   @app.callback(
       dash.dependencies.Output('id-dropdown2', 'value'),
       [dash.dependencies.Input('id-dropdown1', 'value')])
   def dropdown2_update_2(segment_nbr):
       # updated value of dropdown2 depending on value of dropdown1
       return "all"

   ######################################################################################
   # Reactive function to update TS graph
   ######################################################################################
   @app.callback(
       dash.dependencies.Output('main-graph', 'figure'),
       [dash.dependencies.Input('submit-button', 'n_clicks')],
       [dash.dependencies.State('id-dropdown1', 'value'),
        dash.dependencies.State('id-dropdown2', 'value')])
   def update_graph(n_clicks, dd1_value, dd2_value):
       # retrieve data from API
       data = retrieve_data(dd1_value, dd2_value)
       print(data.info())

       # filter the dataframes
       trace0 = go.Scatter(x=data.ds, 
                   y=data.y, 
                   mode="lines+markers", 
                   name="TS data", 
                   opacity = 0.8,
                   marker = dict(color='rgb(0, 0, 0)'))

       layout = dict(
           xaxis=dict(
               rangeselector=dict(
                   buttons=list([
                       dict(count=3,
                            label='3m',
                            step='month',
                            stepmode='backward'),
                       dict(step='all')
                   ])
               ),
               rangeslider=dict(
                   visible = True
               ),
               type='date'
           ),
           shapes=[{
                   'type':'line',
                   'line': {
                       'color': 'rgb(255, 0, 0)',
                       'width': 3,
                   },
               }]
       )

       fig = dict(data=[trace0], layout=layout)
       return fig


   if __name__ == '__main__':
       app.run_server(host='0.0.0.0')

In the above example, there are two dropdown, and the input of the first updates the options of the second. Also, the callback to update the Graph component is done by taking the States of the two Dropdowns, and it is fired through a button component.

The data variable is a pandas data frame and is correctly retrieved from the API (I can check that by printing it). However the Graph is not updating. Retrieving the data from the API takes between 20s to 100s.

Here is a sample output displayed by the server:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3169 entries, 0 to 3168
Data columns (total 2 columns):
ds    3169 non-null object
y     3169 non-null int64
dtypes: int64(1), object(1)
memory usage: 49.6+ KB
None
172.19.227.81 - - [07/Sep/2018 14:37:05] "POST /_dash-update-component HTTP/1.1" 200 - 

It seems that the components is being updated, but no.

This is my current setup: Anaconda python 3. Dash installed from PyPI: dash-core-components (0.28.2), dash-html-components (0.12.0), dash (0.26.4) and dash_renderer (0.13.2).

Any help will be appreciated!

I’m experimenting a similar issue. In my case I have a Dash app that shows table(dash-table-experiments). It has some filters that affects the table.

My main callback definition is:

@APP.callback(Output('table', 'rows'),
              [Input('zone', 'value'),
               Input('responsible_radio', 'value'),
               Input('responsible_dropdown', 'value'),
               Input('int_state', 'value'),
               Input('zone_type', 'value'),
               Input('today_closed', 'value'),
               Input('ticket_search', 'value'),
               Input('solved_tickets', 'value')])
def fill_table(zone, responsible, resp_dd, int_state, zone_type, closed_today, search, solved): 
   if solved == value1:
       ...
       print(df['column1'].unique())
       print('VALUE1')
       return df.to_dict('records)
   elif solved == value2:
       ...
       print(df['column1'].unique())
       print('VALUE2')
       return df.to_dict('records)

solved is a radio_button input (dash-core-components). df is a pandas dataframe. Other elements are strings.

In first instance, when the dash is loaded, it works fine. When I select value2, everything goes fine too, but when I select value1 a problem appears.
It seems that the callback is being triggered, because the print shows me that VALUE1 is being selected and the dataframe prints the column1 unique values corresponding the ones that should appear when I select VALUE1.

The problem is that the table doesn’t update. Rows changes when I first select the second option of the radio button. When I return to the first one, even that the prints tells me that the callback is triggered and the rows will change, the table doesn’t update.

There is another callback triggered when table rows are updated.

@APP.callback(Output('row_counter', 'children'),
                     [Input('table', 'rows')])
def get_row_num(rows):
    print('Rows have changed')
    return "   \t   Visualizing {} rows in the table.".format(len(rows)) 

The first time I click the second option of the radio button, this callback triggers and shows me the number of rows my table will have and it updates the table with that number of rows (as expected). My problem is that when I select the first value once again in the radio button, the callback of ‘get_row_num’ isn’t getting triggered. It doesn’t print ‘Rows have changed’ and doesn’t update the table.

Callbacks are being fired fired but components aren’t being updated.

It’s not the first time I have this issue, I had to use some nasty tricks to solve this in other cases, I think this should work properly.

Im running this over Windows 10, Python 3.6.5
dash: 0.28.5
dash-core-components: 0.35.0
dash-html-components: 0.13.2
dash-renderer: 0.13.0
dash-table-experiments: 0.6.0

Same problem here. I see in my logs that the callback is triggered and that the number of rows in the table should be changed to X, but on the frontend I see this simply does not happen.

FWIW: the issues became apparent when i made the table editable. Before that, things were more reliable. @chriddyp is this a known issue?

Am seeing the same issue on github by another user: https://github.com/plotly/dash-table/issues/386

NB: there is a useful followup in the github issue with a workaround that works great for my case

Is there any update on that? I am experiencing a similar issue. I am updating a graph via a dropdown. I am printing the selections inside the functions and they seem to be updated alright, but the graph isn’t. I have check my setup with a State callback but still it does not work.