Skip to content

Commit 3a229eb

Browse files
committed
Allow dict id in target_components
1 parent 17fca44 commit 3a229eb

File tree

2 files changed

+45
-24
lines changed

2 files changed

+45
-24
lines changed

components/dash-core-components/src/components/Loading.react.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ import CubeSpinner from '../fragments/Loading/spinners/CubeSpinner.jsx';
88
import CircleSpinner from '../fragments/Loading/spinners/CircleSpinner.jsx';
99
import DotSpinner from '../fragments/Loading/spinners/DotSpinner.jsx';
1010

11+
const stringifyId = id => {
12+
if (typeof id !== 'object') {
13+
return id;
14+
}
15+
const stringifyVal = v => (v && v.wild) || JSON.stringify(v);
16+
const parts = Object.keys(id)
17+
.sort()
18+
.map(k => JSON.stringify(k) + ':' + stringifyVal(id[k]));
19+
return '{' + parts.join(',') + '}';
20+
};
21+
1122
const spinnerComponentOptions = {
1223
graph: GraphSpinner,
1324
cube: CubeSpinner,
@@ -40,7 +51,7 @@ const loadingSelector = (componentPath, targetComponents) => state => {
4051
if (
4152
targetComponents &&
4253
!any(l => {
43-
const target = targetComponents[l.id];
54+
const target = targetComponents[stringifyId(l.id)];
4455
if (!target) {
4556
return false;
4657
}
@@ -84,6 +95,7 @@ function Loading({
8495
custom_spinner,
8596
}) {
8697
const ctx = window.dash_component_api.useDashContext();
98+
8799
const loading = ctx.useSelector(
88100
loadingSelector(ctx.componentPath, target_components),
89101
equals

components/dash-core-components/tests/integration/loading/test_loading_component.py

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from multiprocessing import Lock
22
from dash import Dash, Input, Output, dcc, html
3+
from dash.dependencies import stringify_id
34
from dash.testing import wait
45
import time
56

@@ -414,9 +415,9 @@ def updateDiv(n_clicks):
414415
assert dash_dcc.get_logs() == []
415416

416417

417-
# multiple components, only one triggers the spinner
418-
def test_ldcp010_loading_component_target_components(dash_dcc):
419-
418+
# update multiple props of same component, only targeted id/prop triggers spinner
419+
# test that target_components id can be a dict id
420+
def test_ldcp011_loading_component_target_components(dash_dcc):
420421
lock = Lock()
421422

422423
app = Dash(__name__)
@@ -425,53 +426,61 @@ def test_ldcp010_loading_component_target_components(dash_dcc):
425426
[
426427
dcc.Loading(
427428
[
428-
html.Button(id="btn-1"),
429+
html.Button(id={"type": "button", "index": "one"}),
429430
html.Button(id="btn-2"),
431+
html.Button(id="btn-3"),
430432
],
431433
className="loading-1",
432-
target_components={"btn-2": "children"},
434+
target_components={
435+
stringify_id({"type": "button", "index": "one"}): "className"
436+
},
433437
)
434438
],
435439
id="root",
436440
)
437441

438-
@app.callback(Output("btn-1", "children"), [Input("btn-2", "n_clicks")])
442+
@app.callback(
443+
Output({"type": "button", "index": "one"}, "children"),
444+
[Input("btn-2", "n_clicks")],
445+
)
439446
def updateDiv1(n_clicks):
440447
if n_clicks:
441448
with lock:
442449
return "changed 1"
443-
444450
return "content 1"
445451

446-
@app.callback(Output("btn-2", "children"), [Input("btn-1", "n_clicks")])
452+
@app.callback(
453+
Output({"type": "button", "index": "one"}, "className"),
454+
[Input("btn-3", "n_clicks")],
455+
)
447456
def updateDiv2(n_clicks):
448457
if n_clicks:
449458
with lock:
450-
return "changed 2"
451-
452-
return "content 2"
459+
return "new-class"
460+
return ""
453461

454462
dash_dcc.start_server(app)
455463

456-
dash_dcc.wait_for_text_to_equal("#btn-1", "content 1")
457-
dash_dcc.wait_for_text_to_equal("#btn-2", "content 2")
464+
btn1id = "#" + stringify_id({"type": "button", "index": "one"})
458465

459-
with lock:
460-
dash_dcc.find_element("#btn-1").click()
461-
462-
dash_dcc.find_element(".loading-1 .dash-spinner")
463-
dash_dcc.wait_for_text_to_equal("#btn-2", "")
464-
465-
dash_dcc.wait_for_text_to_equal("#btn-2", "changed 2")
466+
dash_dcc.wait_for_text_to_equal(btn1id, "content 1")
466467

467468
with lock:
468469
dash_dcc.find_element("#btn-2").click()
469-
spinners = dash_dcc.find_elements(".loading-1 .dash-spinner")
470-
dash_dcc.wait_for_text_to_equal("#btn-1", "")
471470

472-
dash_dcc.wait_for_text_to_equal("#btn-1", "changed 1")
471+
spinners = dash_dcc.find_elements(".loading-1 .dash-spinner")
472+
dash_dcc.wait_for_text_to_equal(btn1id, "")
473+
dash_dcc.wait_for_text_to_equal(btn1id, "changed 1")
473474
assert spinners == []
474475

476+
with lock:
477+
dash_dcc.find_element("#btn-3").click()
478+
479+
dash_dcc.find_element(".loading-1 .dash-spinner")
480+
dash_dcc.wait_for_text_to_equal(btn1id, "")
481+
482+
dash_dcc.wait_for_class_to_equal(btn1id, "new-class")
483+
475484
assert dash_dcc.get_logs() == []
476485

477486

0 commit comments

Comments
 (0)