Skip to content

Conversation

@CNFeffery
Copy link
Contributor

For the scenario corresponding to #3493, add a new parameter hide_all_callbacks to Dash(), which is used to change the default application value of the hidden parameter in app.callback(), improving the convenience of callback debugging for complex applications. Example:

image
import dash
from dash import html, Input, Output, State

app = dash.Dash(__name__, hide_all_callbacks=True)

app.layout = html.Div(
    [
        html.Div(
            [
                html.Button("Button 1", id="button1"),
                html.Button("Button 2", id="button2"),
                html.Button("Button 3", id="button3"),
            ]
        ),
        html.Div(0, id="output"),
    ],
    style={"padding": 50},
)


@app.callback(
    Output("output", "children"),
    Input("button1", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
)
def button1_update_output(n_clicks, children):
    return children + 1


@app.callback(
    Output("output", "children", allow_duplicate=True),
    Input("button2", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
)
def button2_update_output(n_clicks, children):
    return children + 1


@app.callback(
    Output("output", "children", allow_duplicate=True),
    Input("button3", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
    hidden=False,
)
def button3_update_output(n_clicks, children):
    return children + 1


if __name__ == "__main__":
    app.run(debug=True)

@CNFeffery CNFeffery marked this pull request as ready for review January 8, 2026 07:15
Comment on lines 181 to 184
config_prevent_initial_callbacks = _kwargs.pop(
"config_prevent_initial_callbacks", False
)
config_hide_all_callbacks = _kwargs.pop("config_hide_all_callbacks", False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are those actually insert when using @callback directly? I think we need a better system for those since we want the same behavior for both @app.callback and @callback.

Think you can refactor these config into a context and use the context instead of passing them around?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are those actually insert when using @callback directly? I think we need a better system for those since we want the same behavior for both @app.callback and @callback.

Think you can refactor these config into a context and use the context instead of passing them around?

Yes, similarly, for prevent_initial_callbacks, the callback functions defined by dash.callback() cannot obtain the setting values from dash.Dash() too.

…config_hide_all_callbacks in _callback.callback()
@CNFeffery
Copy link
Contributor Author

Taking the following application as an example, both the prevent_initial_callbacks and hide_all_callbacks parameters can now work properly in the callback functions defined by app.callback() and dash.callback():

image
import dash
from dash import html, Input, Output, State

app = dash.Dash(__name__, hide_all_callbacks=True, prevent_initial_callbacks=True)

app.layout = html.Div(
    [
        html.Div(
            [
                html.Button("Button 1", id="button1"),
                html.Button("Button 2", id="button2"),
                html.Button("Button 3", id="button3"),
            ]
        ),
        html.Div(0, id="output"),
    ],
    style={"padding": 50},
)


@app.callback(
    Output("output", "children"),
    Input("button1", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
)
def button1_update_output(n_clicks, children):
    return children + 1


@dash.callback(
    Output("output", "children", allow_duplicate=True),
    Input("button2", "n_clicks"),
    State("output", "children"),
)
def button2_update_output(n_clicks, children):
    return children + 1


@app.callback(
    Output("output", "children", allow_duplicate=True),
    Input("button3", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
    hidden=False,
)
def button3_update_output(n_clicks, children):
    return children + 1


if __name__ == "__main__":
    app.run(debug=True)

config_prevent_initial_callbacks = _kwargs.pop(
"config_prevent_initial_callbacks", False
# Get prevent_initial_callbacks and hide_all_callbacks from get_app().config
current_app_config = get_app().config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice usage of get_app, but this will not work if the app hasn't been instanced yet which we can't guarantee with dash.callback.

We can defer it all and map the configs values in the _setup_server after this line:

dash/dash/dash.py

Line 1648 in a9a173f

self._callback_list.extend(_callback.GLOBAL_CALLBACK_LIST)

…ch callback function through the hide_all_callbacks parameter
@CNFeffery
Copy link
Contributor Author

After refactoring, the current hide_all_callbacks parameter can take effect on callback functions defined in various types:

  • Callback functions defined based on dash.callback() before the app is instantiated
  • Callback functions defined based on dash.callback() after the app is instantiated
  • Callback functions defined based on app.callback()

Example application:

image
import dash
from dash import html, Input, Output, State


@dash.callback(
    Output("output", "children", allow_duplicate=True),
    Input("button2", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
)
def button2_update_output(n_clicks, children):
    return children + 1


app = dash.Dash(__name__, hide_all_callbacks=True)

app.layout = html.Div(
    [
        html.Div(
            [
                html.Button("Button 1", id="button1"),
                html.Button("Button 2", id="button2"),
                html.Button("Button 3", id="button3"),
            ]
        ),
        html.Div(0, id="output"),
    ],
    style={"padding": 50},
)


@app.callback(
    Output("output", "children"),
    Input("button1", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
)
def button1_update_output(n_clicks, children):
    return children + 1


@dash.callback(
    Output("output", "children", allow_duplicate=True),
    Input("button3", "n_clicks"),
    State("output", "children"),
    prevent_initial_call=True,
    hidden=False,
)
def button3_update_output(n_clicks, children):
    return children + 1


if __name__ == "__main__":
    app.run(debug=True)

@CNFeffery CNFeffery requested a review from T4rk1n January 9, 2026 15:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants