From 3be7edaf9a8ee8d8168a309c4f3d98388f0c52c9 Mon Sep 17 00:00:00 2001 From: philippe Date: Thu, 23 May 2024 13:27:24 -0400 Subject: [PATCH 1/3] Fix clientside no outputs --- dash/_callback.py | 2 + dash/dash-renderer/src/actions/callbacks.ts | 20 ++++---- .../callbacks/test_arbitrary_callbacks.py | 46 ++++++++++++++++++- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/dash/_callback.py b/dash/_callback.py index 3d63d4b21e..8ebc274213 100644 --- a/dash/_callback.py +++ b/dash/_callback.py @@ -549,6 +549,7 @@ def register_clientside_callback( **kwargs, ): output, inputs, state, prevent_initial_call = handle_callback_args(args, kwargs) + no_output = isinstance(output, (list,)) and len(output) == 0 insert_callback( callback_list, callback_map, @@ -559,6 +560,7 @@ def register_clientside_callback( state, None, prevent_initial_call, + no_output=no_output, ) # If JS source is explicitly given, create a namespace and function diff --git a/dash/dash-renderer/src/actions/callbacks.ts b/dash/dash-renderer/src/actions/callbacks.ts index 20961199ff..82d4017adc 100644 --- a/dash/dash-renderer/src/actions/callbacks.ts +++ b/dash/dash-renderer/src/actions/callbacks.ts @@ -278,16 +278,18 @@ async function handleClientside( returnValue = await returnValue; } - zipIfArray(outputs, returnValue).forEach(([outi, reti]) => { - zipIfArray(outi, reti).forEach(([outij, retij]) => { - const {id, property} = outij; - const idStr = stringifyId(id); - const dataForId = (result[idStr] = result[idStr] || {}); - if (retij !== dc.no_update) { - dataForId[cleanOutputProp(property)] = retij; - } + if (outputs) { + zipIfArray(outputs, returnValue).forEach(([outi, reti]) => { + zipIfArray(outi, reti).forEach(([outij, retij]) => { + const {id, property} = outij; + const idStr = stringifyId(id); + const dataForId = (result[idStr] = result[idStr] || {}); + if (retij !== dc.no_update) { + dataForId[cleanOutputProp(property)] = retij; + } + }); }); - }); + } } catch (e) { if (e === dc.PreventUpdate) { status = STATUS.PREVENT_UPDATE; diff --git a/tests/integration/callbacks/test_arbitrary_callbacks.py b/tests/integration/callbacks/test_arbitrary_callbacks.py index b9230baa8d..4a49dba249 100644 --- a/tests/integration/callbacks/test_arbitrary_callbacks.py +++ b/tests/integration/callbacks/test_arbitrary_callbacks.py @@ -1,7 +1,15 @@ import time from multiprocessing import Value -from dash import Dash, Input, Output, html, set_props, register_page +from dash import ( + Dash, + Input, + Output, + html, + set_props, + register_page, + clientside_callback, +) def test_arb001_global_set_props(dash_duo): @@ -188,3 +196,39 @@ def on_click(_): dash_duo.wait_for_style_to_equal( "#output", "background-color", "rgba(255, 0, 0, 1)" ) + + +def test_arb007_clientside_no_output(dash_duo): + app = Dash() + + app.layout = [ + html.Button("start", id="start1"), + html.Button("start2", id="start2"), + html.Div(id="output"), + ] + + clientside_callback( + """ + function(_) { + dash_clientside.set_props('output', {children: 'start1'}) + } + """, + Input("start1", "n_clicks"), + prevent_initial_call=True, + ) + clientside_callback( + """ + function(_) { + dash_clientside.set_props('output', {children: 'start2'}) + } + """, + Input("start2", "n_clicks"), + prevent_initial_call=True, + ) + + dash_duo.start_server(app) + + dash_duo.find_element("#start1").click() + dash_duo.wait_for_text_to_equal("#output", "start1") + dash_duo.find_element("#start2").click() + dash_duo.wait_for_text_to_equal("#output", "start2") From c58bd85d22d8b754495ef852796a2686a023cc3d Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 27 May 2024 10:05:59 -0400 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cce75d54fc..f18607dc73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). - [#2854](https://github.com/plotly/dash/pull/2854) Fix dcc.Dropdown resetting empty values to null and triggering callbacks. Fixes [#2850](https://github.com/plotly/dash/issues/2850) - [#2859](https://github.com/plotly/dash/pull/2859) Fix base patch operators. fixes [#2855](https://github.com/plotly/dash/issues/2855) - [#2856](https://github.com/plotly/dash/pull/2856) Fix multiple consecutive calls with same id to set_props only keeping the last props. Fixes [#2852](https://github.com/plotly/dash/issues/2852) +- [#2867](https://github.com/plotly/dash/pull/2867) Fix clientside no output callback. Fixes [#2866](https://github.com/plotly/dash/issues/2866) ## [2.17.0] - 2024-05-03 From 0cce4c00571482fa07ca24f4ef71157d09bd5852 Mon Sep 17 00:00:00 2001 From: philippe Date: Mon, 27 May 2024 11:32:37 -0400 Subject: [PATCH 3/3] build