my goal is to trigger a callback from the keyboard key press. but I found after some googling that dash has limited capability of doing that. I need to use JS and clientside_callback to capture keyboard events. am i correct or dash can do this natively?
so i wrote a clint-side callback which will change the value of an input field upon pressing some desired key. this is working fine. the value is changing.
The second callback i wrote, which is supposed to trigger if the input field is changed. but when JS changes the value of the input, the callback is not triggering but if I manually type inside the input field, then the callback is triggering fine for each keypress. Here is my code:
import dash
from dash import html, dcc
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
app.layout = html.Div([
html.Div(id="output"),
html.Button("Invisible Button", id="invisible-button", style={"opacity": "0", "position": "absolute", "left": "-9999px"}),
dcc.Input(id='last-key-pressed'),
])
app.clientside_callback(
"""
function(n_clicks) {
document.addEventListener('keydown', function(event) {
const allowedKeys = ['ArrowLeft', 'ArrowRight', 'Enter'];
if (allowedKeys.includes(event.key)) {
return event.key; // Return an object with the pressed key
document.getElementById('last-key-pressed').dispatchEvent(new Event('input'));
}
});
return window.dash_clientside.no_update; // Return no_update if not an allowed key
}
""",
Output('last-key-pressed', 'value'),
[Input('invisible-button', 'n_clicks')],
)
@app.callback(
Output('output', 'children'),
[Input('last-key-pressed', 'value')],
prevent_initial_call=True
)
def handle_key_press(last_key_data):
print(last_key_data)
if last_key_data is None:
raise PreventUpdate
last_key_pressed = last_key_data
return f"Last key pressed: {last_key_pressed}"
if __name__ == '__main__':
app.run_server(debug=True)