Identifying Ctrl key press with a button click in Dash

Hello everyone,

I’m currently working on a Dash application where I need to detect if the Ctrl key is pressed while a button is clicked. I understand that this is not a standard feature in Dash, so I’ve attempted to implement this using clientside callbacks and JavaScript.

Here’s an outline of what I’ve done:

  1. I created a hidden Div to store the state of the Ctrl key.
  2. I wrote JavaScript code to detect the Ctrl key press and release events and update the hidden Div accordingly.
  3. I used a clientside callback to call the JavaScript function each time the button is clicked.
  4. I attempted to read the state of the Ctrl key from the hidden Div in a serverside callback.

Despite these steps, I’m having difficulty correctly identifying the state of the Ctrl key in my serverside callback. The callback does not seem to receive the updated state of the Ctrl key as set by the JavaScript code.

Here’s my Python code:

pythonCopy code

import dash
import dash_html_components as html
from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

app.layout = html.Div([
    html.Button('Submit', id='my-button', n_clicks=0),
    html.Div(id='ctrl-key', style={'display': 'none'}),
    html.Div(id='output')
])

@app.callback(
    Output('output', 'children'),
    Input('my-button', 'n_clicks'),
    State('ctrl-key', 'children')
)
def update_output(n_clicks, ctrl_key_pressed):
    if n_clicks > 0:
        if ctrl_key_pressed == 'True':
            return 'Button clicked with Ctrl key pressed'
        else:
            return 'Button clicked without Ctrl key'
    return ''

app.clientside_callback(
    """
    function() {
        return dash_clientside.my_clientside.ctrl_check();
    }
    """,
    Output('ctrl-key', 'children'),
    Input('my-button', 'n_clicks')
)

if __name__ == '__main__':
    app.run_server(debug=True)

And here’s my JavaScript code:

javascriptCopy code

window.dash_clientside = Object.assign({}, window.dash_clientside, {
    my_clientside: {
        ctrl_check: function() {
            document.onkeydown = function(event) {
                if (event.ctrlKey) {
                    document.getElementById('ctrl-key').innerText = 'True';
                }
            }
            document.onkeyup = function(event) {
                if (!event.ctrlKey) {
                    document.getElementById('ctrl-key').innerText = 'False';
                }
            }
            return window.dash_clientside.no_update;
        }
    }
});

I’ve checked my JavaScript code and it seems to correctly detect the Ctrl key events. I’ve also ensured that the hidden Div is correctly identified and updated by the JavaScript code. However, the serverside callback doesn’t seem to read the updated state of the Ctrl key.

I would greatly appreciate any insights or suggestions on how I might solve this issue. If there’s a better or more standard way to achieve what I’m trying to do, I’d be interested to learn about it too.

Thank you in advance for your help!

Hello @wowwwn,

Have you checked out dash-extensions?

Take a look here:

2 Likes

I think the easiest approach would be to wrap the component(s) in an EventListener component, configure it to listen for ctrl key events, and then add that as State for the callback.

1 Like