Skip to content

Commit 89a08e7

Browse files
authored
Merge pull request #3415 from CNFeffery/dev
Fix the client-side callback with multiple Outputs return single no_update
2 parents 6afd6f9 + ae473a6 commit 89a08e7

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
1212
## Fixed
1313
- [#3395](https://github.com/plotly/dash/pull/3395) Fix Components added through set_props() cannot trigger related callback functions. Fix [#3316](https://github.com/plotly/dash/issues/3316)
1414
- [#3397](https://github.com/plotly/dash/pull/3397) Add optional callbacks, suppressing callback warning for missing component ids for a single callback.
15+
- [#3415](https://github.com/plotly/dash/pull/3415) Fix the error triggered when only a single no_update is returned for client-side callback functions with multiple Outputs. Fix [#3366](https://github.com/plotly/dash/issues/3366)
1516

1617
## [3.2.0] - 2025-07-31
1718

dash/dash-renderer/src/actions/callbacks.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,16 @@ function refErr(errors: any, paths: any) {
226226
const getVals = (input: any) =>
227227
Array.isArray(input) ? pluck('value', input) : input.value;
228228

229-
const zipIfArray = (a: any, b: any) =>
230-
Array.isArray(a) ? zip(a, b) : [[a, b]];
229+
const zipIfArray = (a: any, b: any) => {
230+
if (Array.isArray(a)) {
231+
// For client-side callbacks with multiple Outputs, only return a single dash_clientside.no_update
232+
if (b === (window as any).dash_clientside.no_update) {
233+
return zip(a, [b]);
234+
}
235+
return zip(a, b);
236+
}
237+
return [[a, b]];
238+
};
231239

232240
function cleanOutputProp(property: string) {
233241
return property.split('@')[0];
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from dash import (
2+
Dash,
3+
Input,
4+
Output,
5+
html,
6+
clientside_callback,
7+
)
8+
9+
10+
def test_cmorsnu001_clientside_multiple_output_return_single_no_update(dash_duo):
11+
app = Dash(__name__)
12+
app.layout = html.Div(
13+
[
14+
html.Button("trigger", id="trigger-demo"),
15+
html.Div("demo1", id="output-demo1"),
16+
html.Div("demo2", id="output-demo2"),
17+
],
18+
style={"padding": 50},
19+
)
20+
21+
clientside_callback(
22+
"""(n_clicks) => {
23+
try {
24+
return window.dash_clientside.no_update;
25+
} catch (e) {
26+
return [null, null];
27+
}
28+
}""",
29+
Output("output-demo1", "children"),
30+
Output("output-demo2", "children"),
31+
Input("trigger-demo", "n_clicks"),
32+
prevent_initial_call=True,
33+
)
34+
35+
dash_duo.start_server(app)
36+
37+
trigger_clicker = dash_duo.wait_for_element("#trigger-demo")
38+
trigger_clicker.click()
39+
dash_duo.wait_for_text_to_equal(
40+
"#output-demo1",
41+
"demo1",
42+
)
43+
dash_duo.wait_for_text_to_equal(
44+
"#output-demo2",
45+
"demo2",
46+
)

0 commit comments

Comments
 (0)