Reputation: 21
I am creating a webapp that should provide the python code with a callback whenever user rightclicks in the webapp.
I tried to do this with a dcc.Store and to write to the store on a contextmenu event. So far so good. I put this custom code that catches the contextmenu event in assets/custom.js, however, when I try to get the store with var store = document.getElementById("contextmenu_data");
, it returns null, thus never actually writing something to the store. What could be wrong?
Here is an MRE for the python and JS code:
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import threading
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div(id="output"),
dcc.Store(id='contextmenu_data'),
])
@app.callback(Output("output", 'children'),
Input("contextmenu_data", 'data'),
)
def right_click_action(data):
print(f"right_click_action called with data: {data}")
if data:
return f"coordinates are {data}"
return "no rightclicks have happened"
def run_dash():
app.run_server(debug=False)
if __name__ == '__main__':
server = threading.Thread(target=run_dash, daemon=True)
server.start()
window.onload = function() {
document.addEventListener('contextmenu', function(event) {
event.preventDefault();
var store = document.getElementById("contextmenu_data");
console.log(store);
if (store) {
var data = {x: event.clientX, y: event.clientY};
store.setAttribute('data', JSON.stringify(data));
store.dispatchEvent(new CustomEvent('data'));
}
});
};
Upvotes: 2
Views: 39
Reputation: 21
The following was the solution (If you're interested, Copilot and ChatGPT failed to answer this, but Deepseek R1 managed)
Python
import dash
from dash import dcc, html, Input, Output, ClientsideFunction
import threading
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Store(id='contextmenu_data', data={"x": 0, "y": 0}),
html.Div(id="output"),
html.Div(id='dummy', style={'display': 'none'}) # Dummy div to trigger initial setup
])
app.clientside_callback(
ClientsideFunction(namespace="clientside", function_name="captureRightClick"),
Output("contextmenu_data", "data"),
Input("dummy", "children"),
)
@app.callback(Output("output", 'children'),
Input("contextmenu_data", 'data'))
def right_click_action(data):
print(f"right_click_action called with data: {data}")
if data:
return f"Coordinates are {data}"
return "No right-clicks have happened"
def run_dash():
app.run_server(debug=False)
if __name__ == '__main__':
server = threading.Thread(target=run_dash, daemon=True)
server.start()
Javascript
window.dash_clientside = Object.assign({}, window.dash_clientside, {
clientside: {
captureRightClick: function() {
document.addEventListener('contextmenu', function(event) {
event.preventDefault();
const data = { x: event.clientX, y: event.clientY };
console.log("Right-click detected:", JSON.stringify(data));
dash_clientside.set_props('contextmenu_data', { data: data });
});
return window.dash_clientside.no_update;
}
}
});
Upvotes: 0