Hi,
I see some strange behavior with components in the front-end not updating even when the callback function is clearly called. The behavior seems to be similar to this older issue which was fixed a long time ago:
I reduced the problem to a sample app:
import dash
import dash_table
import pandas as pd
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import plotly.graph_objs as go
app = dash.Dash(__name__)
server = app.server
app.layout = html.Div(children=[
dash_table.DataTable(
id='table-data',
data=[{'x':'test', 'graph': 0}],
columns=[
{'id': 'x', 'name': 'x', 'editable':False},
{'id': 'graph', 'name': 'graph', 'presentation': 'dropdown', 'editable':True}],
dropdown={
'graph': {
'options': [
{'label': 'Do not show', 'value': 0x0},
{'label': 'Plot 1', 'value': 1},
{'label': 'Plot 2', 'value': 2}],
},
},
row_deletable=False,
editable=True,
),
dcc.Store(id='g1buffer', storage_type='memory'),
dcc.Store(id='g2buffer', storage_type='memory'),
dcc.Graph(id='plot-graph1'),
dcc.Graph(id='plot-graph2'),
])
@app.callback(
Output('plot-graph1', 'figure'),
[Input('g1buffer', 'data')],
)
def update_graph1(data):
if data is None:
raise PreventUpdate
return data
@app.callback(
Output('plot-graph2', 'figure'),
[Input('g2buffer', 'data')],
)
def update_graph2(data):
if data is None:
raise PreventUpdate
return data
@app.callback(
[
Output('g1buffer', 'data'),
Output('g2buffer', 'data'),
],
[Input('table-data', 'data')],
)
def update_on_table(table_data):
data = go.Scatter(
x=[1,2,3,4],
y=[2,5,1,3],
)
g1 = {}
g2 = {}
if table_data[0]['graph'] == 1:
g1 = {'data': [data]}
if table_data[0]['graph'] == 2:
g2 = {'data': [data]}
return g1, g2
if __name__ == '__main__':
app.run_server(debug=True)
To give a bit more context: I have a callback which generates figures for multiple graph components. However, when one graph is updated, I don’t want loading bars showing on all graphs, but only the one which is changing. The only way I figured out to make this work is having a store (or hidden div) for every graph so you can update all the stores but the ones not changing will just send a PreventUpdate.
In the example above, you should see data in the top graph if ‘Plot 1’ is selected in the table and so on. What I see is that this works fine for Plot 2 but not 1.
The strange thing is, this works if I run this example in uwsgi vs the integrated debug server. In my actual app, it is the other way round, it works in dev but not in the uwsgi deployment.
One thing which seems to make it work in any case is setting row_deletable
to false. This will have an undesired impact on the app though, so I don’t want to go that way. Right now, my best work-around is to have a dummy buffer for the first output component of the update_on_table()
function and use the second, third, etc output for actual graph components.
My skills in React and JS are pretty non-existent so I’m lost as soon as the problems leaves the Python domain. I’d appreciate any comment.