Dear Dash Community,
I have a problem with a circular dependency in a multi-page Dash app. Usually, I ignore those warnings as the callbacks still fire, but this time it’s different. See below a simplified version:
import dash
import time
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output
from dash import callback_context, no_update
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Card(
[
html.Div(id="start-trigger"),
html.Div(id="finished-trigger"),
dbc.Button(
dbc.Row(
[
dbc.Spinner(id="button-spinner", size="sm",
spinner_style={"display": "none"}),
"Start Calculation"
],
no_gutters=True
),
id="start-button",
color="success",
size="md",
n_clicks=0
),
]
)
@app.callback(
[Output("start-button", "disabled"),
Output("button-spinner", "spinner_style"),
Output("start-trigger", "children")],
[Input("start-button", "n_clicks"),
Input("finished-trigger", "children")],
prevent_initial_call=True)
def helper_calculation(_, __):
if callback_context.triggered[0]["prop_id"] == "start-button.n_clicks":
return True, {"margin": ".3rem .65rem 0 0"}, "start-trigger"
else:
return False, {"display": "none"}, no_update
@app.callback(
Output("finished-trigger", "children"),
[Input("start-trigger", "children")],
prevent_initial_call=True)
def long_calculation(_):
time.sleep(5)
return "calculation finished"
if __name__ == "__main__":
app.run_server(debug=True)
The code is supposed to do the following:
-
Upon button press, the button shall be deactivated to prevent further callbacks of the same calculation, the progress-spinner shall be shown, and the start-trigger (invisible Div) shall be updated
-
Upon a change of the start-trigger, the long calculation shall be started and once it’s finished, the finished-trigger shall be updated
-
Upon a change of the finished-trigger, the button shall be activated again and the progress-spinner shall become invisible again. Notice the “no_update” in the else tree of the first callback to prevent the same calculation from happening again.
Currently, step 1 and 2 work. But although the finished trigger is updated, the first callback is not triggered and hence the spinner keeps spinning and the button stays deactivated
Any idea how I can make this work?