Skip to content

Commit 3532997

Browse files
committed
Added triggered_id to clientside callbacks
1 parent 3adb9a9 commit 3532997

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ async function handleClientside(
262262
prop_id: prop_id,
263263
value: inputDict[prop_id]
264264
}));
265+
dc.callback_context.triggered_id = getTriggeredId(
266+
payload.changedPropIds
267+
);
265268
dc.callback_context.inputs_list = inputs;
266269
dc.callback_context.inputs = inputDict;
267270
dc.callback_context.states_list = state;
@@ -576,6 +579,16 @@ function inputsToDict(inputs_list: any) {
576579
return inputs;
577580
}
578581

582+
function getTriggeredId(triggered: string[]): string | object {
583+
// for regular callbacks, takes the first triggered prop_id, e.g. "btn.n_clicks" and returns "btn"
584+
// for pattern matching callback, e.g. '{"index":0, "type":"btn"}' and returns {index:0, type: "btn"}'
585+
let componentId = triggered[0].split('.')[0];
586+
if (componentId.startsWith('{')) {
587+
componentId = JSON.parse(componentId);
588+
}
589+
return componentId;
590+
}
591+
579592
export function executeCallback(
580593
cb: IPrioritizedCallback,
581594
config: any,

tests/integration/clientside/assets/clientside.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ window.dash_clientside.clientside = {
6363
return triggered.map(t => `${t.prop_id} = ${t.value}`).join(', ');
6464
},
6565

66+
triggered_id_to_str: function(n_clicks0, n_clicks1) {
67+
const triggered = dash_clientside.callback_context.triggered_id;
68+
const triggered_id = typeof triggered === "string" ? triggered : triggered.btn1
69+
return triggered_id
70+
},
71+
6672
inputs_to_str: function(n_clicks0, n_clicks1) {
6773
const inputs = dash_clientside.callback_context.inputs;
6874
const keys = Object.keys(inputs);

tests/integration/clientside/test_clientside.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,3 +829,45 @@ def test_clsd019_clientside_inline_promise(dash_duo):
829829

830830
dash_duo.start_server(app)
831831
dash_duo.wait_for_text_to_equal("#output-div", "initial-inline")
832+
833+
834+
def test_clsd020_clientside_callback_context_triggered_id(dash_duo):
835+
app = Dash(__name__, assets_folder="assets")
836+
837+
app.layout = html.Div(
838+
[
839+
html.Button("btn0", id="btn0"),
840+
html.Button("btn1:0", id={"btn1": 0}),
841+
html.Button("btn1:1", id={"btn1": 1}),
842+
html.Button("btn1:2", id={"btn1": 2}),
843+
html.Div(id="output-clientside", style={"font-family": "monospace"}),
844+
]
845+
)
846+
847+
app.clientside_callback(
848+
ClientsideFunction(namespace="clientside", function_name="triggered_id_to_str"),
849+
Output("output-clientside", "children"),
850+
[Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")],
851+
)
852+
853+
dash_duo.start_server(app)
854+
855+
dash_duo.wait_for_text_to_equal("#output-clientside", "")
856+
857+
dash_duo.find_element("#btn0").click()
858+
859+
dash_duo.wait_for_text_to_equal(
860+
"#output-clientside",
861+
"btn0",
862+
)
863+
864+
dash_duo.find_element("button[id*='btn1\":0']").click()
865+
866+
dash_duo.wait_for_text_to_equal("#output-clientside", '0')
867+
868+
dash_duo.find_element("button[id*='btn1\":2']").click()
869+
870+
dash_duo.wait_for_text_to_equal(
871+
"#output-clientside",
872+
'2'
873+
)

0 commit comments

Comments
 (0)