From cc00850ba8ca7c0601dbcd4e2f591b6593ff76ac Mon Sep 17 00:00:00 2001 From: nickmelnikov82 Date: Fri, 7 Apr 2023 14:07:35 +0600 Subject: [PATCH 1/5] Fixed the issue 2493. Passing customdata by userclick --- .../src/fragments/Graph.react.js | 15 ++++-- .../integration/graph/test_graph_basics.py | 46 +++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/components/dash-core-components/src/fragments/Graph.react.js b/components/dash-core-components/src/fragments/Graph.react.js index f669b5ccc2..a252eafdd2 100644 --- a/components/dash-core-components/src/fragments/Graph.react.js +++ b/components/dash-core-components/src/fragments/Graph.react.js @@ -87,10 +87,17 @@ const filterEventData = (gd, eventData, event) => { has('customdata', data[pointData.curveNumber]) ) { if (has('pointNumber', fullPoint)) { - pointData.customdata = - data[pointData.curveNumber].customdata[ - fullPoint.pointNumber - ]; + if (fullPoint.pointNumber) { + + pointData.customdata = + data[pointData.curveNumber].customdata[fullPoint.pointNumber]; + } else if ( + !fullPoint.pointNumber + && + fullPoint. data.mode. includes('lines') + ) { + pointData.customdata = data[pointData.curveNumber].customdata + } } else if (has('pointNumbers', fullPoint)) { pointData.customdata = fullPoint.pointNumbers.map(point => { return data[pointData.curveNumber].customdata[point]; diff --git a/components/dash-core-components/tests/integration/graph/test_graph_basics.py b/components/dash-core-components/tests/integration/graph/test_graph_basics.py index 1513a1e59b..9dec3377b8 100644 --- a/components/dash-core-components/tests/integration/graph/test_graph_basics.py +++ b/components/dash-core-components/tests/integration/graph/test_graph_basics.py @@ -321,3 +321,49 @@ def set_data(dataset): assert dash_dcc.wait_for_text_to_equal( "#relayout-data", "[0, -1, -2]" ), "graph data must contain frame [0,-1,-2]" + + +def test_grbs007_graph_scatter_lines_customdata(dash_dcc): + app = Dash(__name__) + + expected_value = 'obj-1' + + scatter_figures = go.Figure( + data=[ + go.Scatter( + x=[0, 1, 1, 0, 0], + y=[1, 1, 2, 2, 1], + mode='lines', + fill='toself', + customdata=[expected_value] + ) + ] + ) + + app.layout = html.Div( + [ + dcc.Graph( + id="scatter-lines", + figure=scatter_figures, + style={"width": 600, "height": 300} + ), + dcc.Textarea(id="test-text-area"), + ], + style={"width": 1000, "height": 500} + ) + + @app.callback(Output("test-text-area", "value"), Input("scatter-lines", "clickData")) + def handleClick(clickData): + return json.dumps(clickData) + + dash_dcc.start_server(app) + dash_dcc.wait_for_element("#scatter-lines") + + dash_dcc.find_elements("g .xy")[0].click() + + data = dash_dcc.wait_for_element("#test-text-area").get_attribute("value") + assert data != "", "graph clickData must contain data" + + data = json.loads(data) + assert "customdata" in data["points"][0], "graph clickData must contain customdata" + assert data["points"][0]["customdata"][0] == expected_value From 73ff08a7191f5002d286b6c036a8ba76db2ad5f6 Mon Sep 17 00:00:00 2001 From: nickmelnikov82 Date: Mon, 10 Apr 2023 14:28:20 +0600 Subject: [PATCH 2/5] Fixed the issue 2493. Passing customdata by userclick. Fix lint. --- .../src/fragments/Graph.react.js | 17 +++++++------ .../integration/graph/test_graph_basics.py | 16 ++++++------ .../clientside/test_clientside_restarts.py | 25 ++++++++----------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/components/dash-core-components/src/fragments/Graph.react.js b/components/dash-core-components/src/fragments/Graph.react.js index a252eafdd2..1cf2306afe 100644 --- a/components/dash-core-components/src/fragments/Graph.react.js +++ b/components/dash-core-components/src/fragments/Graph.react.js @@ -88,18 +88,21 @@ const filterEventData = (gd, eventData, event) => { ) { if (has('pointNumber', fullPoint)) { if (fullPoint.pointNumber) { - pointData.customdata = - data[pointData.curveNumber].customdata[fullPoint.pointNumber]; + data[pointData.curveNumber].customdata[ + fullPoint.pointNumber + ]; } else if ( - !fullPoint.pointNumber - && - fullPoint. data.mode. includes('lines') + !fullPoint.pointNumber && + fullPoint.data.mode.includes('lines') ) { - pointData.customdata = data[pointData.curveNumber].customdata + pointData.customdata = + data[pointData.curveNumber].customdata; } } else if (has('pointNumbers', fullPoint)) { - pointData.customdata = fullPoint.pointNumbers.map(point => { + pointData.customdata = fullPoint.pointNumbers.map(function ( + point + ) { return data[pointData.curveNumber].customdata[point]; }); } diff --git a/components/dash-core-components/tests/integration/graph/test_graph_basics.py b/components/dash-core-components/tests/integration/graph/test_graph_basics.py index 9dec3377b8..5211d3c44d 100644 --- a/components/dash-core-components/tests/integration/graph/test_graph_basics.py +++ b/components/dash-core-components/tests/integration/graph/test_graph_basics.py @@ -326,16 +326,16 @@ def set_data(dataset): def test_grbs007_graph_scatter_lines_customdata(dash_dcc): app = Dash(__name__) - expected_value = 'obj-1' + expected_value = "obj-1" scatter_figures = go.Figure( data=[ go.Scatter( x=[0, 1, 1, 0, 0], y=[1, 1, 2, 2, 1], - mode='lines', - fill='toself', - customdata=[expected_value] + mode="lines", + fill="toself", + customdata=[expected_value], ) ] ) @@ -345,14 +345,16 @@ def test_grbs007_graph_scatter_lines_customdata(dash_dcc): dcc.Graph( id="scatter-lines", figure=scatter_figures, - style={"width": 600, "height": 300} + style={"width": 600, "height": 300}, ), dcc.Textarea(id="test-text-area"), ], - style={"width": 1000, "height": 500} + style={"width": 1000, "height": 500}, ) - @app.callback(Output("test-text-area", "value"), Input("scatter-lines", "clickData")) + @app.callback( + Output("test-text-area", "value"), Input("scatter-lines", "clickData") + ) def handleClick(clickData): return json.dumps(clickData) diff --git a/tests/integration/clientside/test_clientside_restarts.py b/tests/integration/clientside/test_clientside_restarts.py index b1b165f856..2f91c7a011 100644 --- a/tests/integration/clientside/test_clientside_restarts.py +++ b/tests/integration/clientside/test_clientside_restarts.py @@ -12,17 +12,19 @@ def create_app(): app = Dash(__name__) - app.layout = html.Div([ - html.Button("Click", id="click"), - html.Div(id="output"), - html.Div(reloads, id="reload") - ]) + app.layout = html.Div( + [ + html.Button("Click", id="click"), + html.Div(id="output"), + html.Div(reloads, id="reload"), + ] + ) app.clientside_callback( "(n_clicks) => `clicked ${n_clicks}`", Output("output", "children"), Input("click", "n_clicks"), - prevent_initial_call=True + prevent_initial_call=True, ) reloads += 1 return app @@ -35,20 +37,13 @@ def create_app(): dev_tools_hot_reload_max_retry=100, ) - dash_duo_mp.start_server( - create_app(), - **hot_reload_settings - ) + dash_duo_mp.start_server(create_app(), **hot_reload_settings) dash_duo_mp.find_element("#click").click() dash_duo_mp.wait_for_text_to_equal("#output", "clicked 1") dash_duo_mp.server.stop() - dash_duo_mp.start_server( - create_app(), - navigate=False, - **hot_reload_settings - ) + dash_duo_mp.start_server(create_app(), navigate=False, **hot_reload_settings) dash_duo_mp.wait_for_text_to_equal("#reload", "1") dash_duo_mp.find_element("#click").click() # reloaded so 1 again. From bb596bebc688df88eb9342b581320cfd4f1ddbc0 Mon Sep 17 00:00:00 2001 From: nickmelnikov82 Date: Tue, 11 Apr 2023 18:58:54 +0600 Subject: [PATCH 3/5] Fix lint for test_integration.py --- components/dash-html-components/tests/test_integration.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/dash-html-components/tests/test_integration.py b/components/dash-html-components/tests/test_integration.py index 648c869df5..d0551d6e90 100644 --- a/components/dash-html-components/tests/test_integration.py +++ b/components/dash-html-components/tests/test_integration.py @@ -113,8 +113,12 @@ def test_click_static(dash_duo): [ html.Div("no event listener", className="div-1"), html.Div("event listener", id="div-2", n_clicks=0), - html.Div("no event listener", id="div-3", n_clicks=0, disable_n_clicks=True), - html.Div("event listener", id="div-4", n_clicks=0, disable_n_clicks=False), + html.Div( + "no event listener", id="div-3", n_clicks=0, disable_n_clicks=True + ), + html.Div( + "event listener", id="div-4", n_clicks=0, disable_n_clicks=False + ), html.Div(id="div-output"), ] ) From f8c5fbcc84778c939fcdf3489ad45d080ae710b5 Mon Sep 17 00:00:00 2001 From: nickmelnikov82 Date: Wed, 12 Apr 2023 12:17:07 +0600 Subject: [PATCH 4/5] Fix missed first index element --- components/dash-core-components/src/fragments/Graph.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dash-core-components/src/fragments/Graph.react.js b/components/dash-core-components/src/fragments/Graph.react.js index 1cf2306afe..bed0975b89 100644 --- a/components/dash-core-components/src/fragments/Graph.react.js +++ b/components/dash-core-components/src/fragments/Graph.react.js @@ -87,7 +87,7 @@ const filterEventData = (gd, eventData, event) => { has('customdata', data[pointData.curveNumber]) ) { if (has('pointNumber', fullPoint)) { - if (fullPoint.pointNumber) { + if (typeof fullPoint.pointNumber === 'number') { pointData.customdata = data[pointData.curveNumber].customdata[ fullPoint.pointNumber From 5f6fec255527efc2946f9837ce744112f4873aea Mon Sep 17 00:00:00 2001 From: nickmelnikov82 Date: Thu, 27 Apr 2023 11:57:58 +0600 Subject: [PATCH 5/5] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 791b88c910..520af6c076 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## Fixed - [#2491](https://github.com/plotly/dash/pull/2491) Fix clientside inline function name not found, fix [#2488](https://github.com/plotly/dash/issues/2488) +- [#2500](https://github.com/plotly/dash/pull/2500) Passing customdata by click for scattermapbox, fix [#2493](https://github.com/plotly/dash/issues/2493) ## [2.9.2] - 2023-03-29