there are a few questions around that topic either here or on the plotly forum but I can't get it to work on my dashboard and having a hard time finding the correct solution.
In a nutshell and for the sake of clarity, one page on my dashboard contains an Input box, a button and 2x Div where two graphs are loaded.
layout = html.Div([
dbc.Container([
dbc.Row([
dbc.Col('Symbol: '),
dbc.Col(dcc.Input(id='pcal_symbol', placeholder='enter a stock ticker')),
]),
html.Br(),
dbc.Row([html.Button("Plot", id='submit_pcal', n_clicks=0)]),
html.Br(),
html.Div(id='pcal_rv_graph'),
html.Div(id='pcal_rv_perc_graph'),
])
])
So I submit an Input and upon clicking on the button I gather the corresponding data (from.json flat files) and produce the two graph. After reading on this issue on the forum, it appears I need to load the json into dataframe from within the callback (instead of delaring the dataframes as a local variable). Here is my callback:
@app.callback(
[
Output('pcal_rv_graph', 'children'),
Output('pcal_rv_perc_graph', 'children')
],
[
Input('submit_pcal', 'n_clicks'),
],
[
State('pcal_symbol', 'value'),
],
prevent_initial_call=True
)
def update_plot(n_clicks, symbol):
if n_clicks is not None:
ticker = str(symbol).upper()
fig1 = go.Figure()
fig2 = go.Figure()
#fecth the data
df1 = pd.read_json(...)
df2 = pd.read_json(...)
fig1.add_trace(go.Scatter(x=df1['date'], y=df1['ind1'], mode='lines+markers'))
fig2.add_trace(go.Scatter(x=df2['date'], y=df2['ind2'], mode='lines+markers'))
return [dcc.Graph(id='pcal_rv_graph', figure=fig1),
dcc.Graph(id='pcal_rv_perc_graph', figure=fig2)]
The first time I enter a symbol in my Input box, the graphs are shown correctly; but if I change the Input to another symbol, the graphs are not updated. When debugging I can see that the new symbol is being updated and the data is being fetched but somehow the graphs won't update. I don't think I need a dbc Interval component as my data source is updated daily so this is not for live graphs. Moreover I am loading the data within the callback and I would prefer not having some hidden Div to store my data (this would mean saving 8 or 9 dataframes for my full dahsboard not just 2 like in my example above). From what I read, this would make things much slower. Not sure if this is important but for the callback I do load more State functions (5 default parameters)
Edit: from the plotly documentation:
The callback returns the correct output the very first time it is called, but once the global df variable is modified, any subsequent callback that uses that dataframe is not using the original data anymore.
This is my problem. However it feels like I am following what they offer as solution, that is using an intermediary dataframe being initialized within the callback...
Edit2: updated
Edit3: I think I found a "fix" html.Div(id='...') is where a graph should be loaded and originally my callback returns dcc.Graph(id, fig). If I specify dcc.Graph(id) instead of html.Div as my graph container and return fig in my callback then the figures are updated correctly. Now I need to figure out how to hide the empty graphs at the start...