Skip to content

Commit

Permalink
Merge pull request #2695 from AnnMarieW/clientside-triggered_id
Browse files Browse the repository at this point in the history
Added triggered_id to clientside callbacks
  • Loading branch information
alexcjohnson authored Dec 1, 2023
2 parents f70b3db + 81fd848 commit 2153a68
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 0 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).

## [UNRELEASED]

### Added
- [#2695](https://github.com/plotly/dash/pull/2695) Adds `triggered_id` to `dash_clientside.callback_context`. Fixes [#2692](https://github.com/plotly/dash/issues/2692)

## [2.14.2] - 2023-11-27

## Fixed
Expand Down
15 changes: 15 additions & 0 deletions dash/dash-renderer/src/actions/callbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ async function handleClientside(
prop_id: prop_id,
value: inputDict[prop_id]
}));
dc.callback_context.triggered_id = getTriggeredId(
payload.changedPropIds
);
dc.callback_context.inputs_list = inputs;
dc.callback_context.inputs = inputDict;
dc.callback_context.states_list = state;
Expand Down Expand Up @@ -576,6 +579,18 @@ function inputsToDict(inputs_list: any) {
return inputs;
}

function getTriggeredId(triggered: string[]): string | object | undefined {
// for regular callbacks, takes the first triggered prop_id, e.g. "btn.n_clicks" and returns "btn"
// for pattern matching callback, e.g. '{"index":0, "type":"btn"}' and returns {index:0, type: "btn"}'
if (triggered && triggered.length) {
let componentId = triggered[0].split('.')[0];
if (componentId.startsWith('{')) {
componentId = JSON.parse(componentId);
}
return componentId;
}
}

export function executeCallback(
cb: IPrioritizedCallback,
config: any,
Expand Down
6 changes: 6 additions & 0 deletions tests/integration/clientside/assets/clientside.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ window.dash_clientside.clientside = {
return triggered.map(t => `${t.prop_id} = ${t.value}`).join(', ');
},

triggered_id_to_str: function(n_clicks0, n_clicks1) {
const triggered = dash_clientside.callback_context.triggered_id;
const triggered_id = typeof triggered === "string" ? triggered : triggered.btn1
return triggered_id
},

inputs_to_str: function(n_clicks0, n_clicks1) {
const inputs = dash_clientside.callback_context.inputs;
const keys = Object.keys(inputs);
Expand Down
39 changes: 39 additions & 0 deletions tests/integration/clientside/test_clientside.py
Original file line number Diff line number Diff line change
Expand Up @@ -829,3 +829,42 @@ def test_clsd019_clientside_inline_promise(dash_duo):

dash_duo.start_server(app)
dash_duo.wait_for_text_to_equal("#output-div", "initial-inline")


def test_clsd020_clientside_callback_context_triggered_id(dash_duo):
app = Dash(__name__, assets_folder="assets")

app.layout = html.Div(
[
html.Button("btn0", id="btn0"),
html.Button("btn1:0", id={"btn1": 0}),
html.Button("btn1:1", id={"btn1": 1}),
html.Button("btn1:2", id={"btn1": 2}),
html.Div(id="output-clientside", style={"font-family": "monospace"}),
]
)

app.clientside_callback(
ClientsideFunction(namespace="clientside", function_name="triggered_id_to_str"),
Output("output-clientside", "children"),
[Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")],
)

dash_duo.start_server(app)

dash_duo.wait_for_text_to_equal("#output-clientside", "")

dash_duo.find_element("#btn0").click()

dash_duo.wait_for_text_to_equal(
"#output-clientside",
"btn0",
)

dash_duo.find_element("button[id*='btn1\":0']").click()

dash_duo.wait_for_text_to_equal("#output-clientside", "0")

dash_duo.find_element("button[id*='btn1\":2']").click()

dash_duo.wait_for_text_to_equal("#output-clientside", "2")

0 comments on commit 2153a68

Please sign in to comment.