From b4d5846e4beeedc746bf62225d9dc41b79d90e3e Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Fri, 1 May 2020 17:12:19 -0400 Subject: [PATCH 1/2] fix #1223 - initialcall on new layout chunk edge case --- dash-renderer/src/actions/dependencies.js | 8 +++- .../callbacks/test_multiple_callbacks.py | 40 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/dash-renderer/src/actions/dependencies.js b/dash-renderer/src/actions/dependencies.js index 59f398b010..a5bb3fead0 100644 --- a/dash-renderer/src/actions/dependencies.js +++ b/dash-renderer/src/actions/dependencies.js @@ -1214,10 +1214,14 @@ export function getCallbacksInLayout(graphs, paths, layoutChunk, opts) { if (callback) { const foundIndex = foundCbIds[callback.resolvedId]; if (foundIndex !== undefined) { - callbacks[foundIndex].changedPropIds = mergeMax( - callbacks[foundIndex].changedPropIds, + const foundCb = callbacks[foundIndex]; + foundCb.changedPropIds = mergeMax( + foundCb.changedPropIds, callback.changedPropIds ); + if (callback.initialCall) { + foundCb.initialCall = true; + } } else { foundCbIds[callback.resolvedId] = callbacks.length; callbacks.push(callback); diff --git a/tests/integration/callbacks/test_multiple_callbacks.py b/tests/integration/callbacks/test_multiple_callbacks.py index 009c8e7d10..ef807236d2 100644 --- a/tests/integration/callbacks/test_multiple_callbacks.py +++ b/tests/integration/callbacks/test_multiple_callbacks.py @@ -262,3 +262,43 @@ def on_click(n_clicks): dash_duo.wait_for_text_to_equal("#output", "1") dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", "2") + + +def test_cbmt007_early_preventupdate_inputs_above_below(dash_duo): + app = dash.Dash(__name__, suppress_callback_exceptions=True) + app.layout = html.Div(id="content") + + @app.callback(Output("content", "children"), [Input("content", "style")]) + def content(_): + return html.Div([ + html.Div(42, id="above-in"), + html.Div(id="above-dummy"), + html.Hr(), + html.Div(0, id='above-out'), + html.Div(0, id='below-out'), + html.Hr(), + html.Div(id="below-dummy"), + html.Div(44, id="below-in"), + ]) + + # Create 4 callbacks - 2 above, 2 below. + for pos in ('above', 'below'): + @app.callback( + Output("{}-dummy".format(pos), "children"), + [Input("{}-dummy".format(pos), "style")] + ) + def dummy(_): + raise PreventUpdate + + @app.callback( + Output('{}-out'.format(pos), 'children'), + [Input('{}-in'.format(pos), 'children')] + ) + def out(v): + return v + + dash_duo.start_server(app) + + # as of https://github.com/plotly/dash/issues/1223, above-out would be 0 + dash_duo.wait_for_text_to_equal("#above-out", "42") + dash_duo.wait_for_text_to_equal("#below-out", "44") From 3234e4bbe139b5cd8ea8be7b3bf18a6703e94974 Mon Sep 17 00:00:00 2001 From: alexcjohnson Date: Fri, 1 May 2020 17:19:49 -0400 Subject: [PATCH 2/2] changelog for #1224 initialcall fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c84c854d5..e0edbed10e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [#1078](https://github.com/plotly/dash/pull/1078) Permit usage of arbitrary file extensions for assets within component libraries ### Fixed +- [#1224](https://github.com/plotly/dash/pull/1224) Fixes [#1223](https://github.com/plotly/dash/issues/1223), a very specific situation in which initial callbacks will not fire. - [#1220](https://github.com/plotly/dash/pull/1220) Fixes [#1216](https://github.com/plotly/dash/issues/1216), a set of related issues about pattern-matching callbacks with `ALL` wildcards in their `Output` which would fail if no components matched the pattern. - [#1212](https://github.com/plotly/dash/pull/1212) Fixes [#1200](https://github.com/plotly/dash/issues/1200) - prior to Dash 1.11, if none of the inputs to a callback were on the page, it was not an error. This was, and is now again, treated as though the callback raised PreventUpdate. The one exception to this is with pattern-matching callbacks, when every Input uses a multi-value wildcard (ALL or ALLSMALLER), and every Output is on the page. In that case the callback fires as usual. - [#1201](https://github.com/plotly/dash/pull/1201) Fixes [#1193](https://github.com/plotly/dash/issues/1193) - prior to Dash 1.11, you could use `flask.has_request_context() == False` inside an `app.layout` function to provide a special layout containing all IDs for validation purposes in a multi-page app. Dash 1.11 broke this when we moved most of this validation into the renderer. This change makes it work again.