3

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...

Hotone
  • 431
  • 3
  • 18
  • It seems that no matter what your input is, you are always outputting the same columns *ind1* and *ind2*, as your input symbol is only used for the ticker and the ticker isn't used for changing the graph. Assuming the 2 JSON files that you load are always the same, your graph is going to be the same as well. This is why when you replot your graphs they aren't updating, because your code doesn't change the graphs no matter what your input is! – Daniel Al Mouiee Jan 21 '22 at 07:27
  • hi, I should have specified that the fetching data functions for df1 and df2 are dependent on the symbol entered in the Input box. For instance, in a debug mode, after entering 'IBM' as symbol in the input box I see that df1 and df2 are populated with the data for IBM. As this is the first time I enter a symbol resuming the program will produce the graphs. However if I then enter 'AAPL' as symbol, I see that df1 and df2 are updated with the corresponding AAPL data but no graph is being updated. – Hotone Jan 21 '22 at 08:27
  • Can you provide the entire script for complteness please, cause it's a bit hard to say what's the issue as the graphs should be updating from what you have said. – Daniel Al Mouiee Jan 21 '22 at 10:48
  • I added as Edit2 the full callback method – Hotone Jan 21 '22 at 15:25

1 Answers1

0

I solved it by using my Edit3 in OP and initializing the figures to a blank figure using this answer

Hotone
  • 431
  • 3
  • 18