Changing the value of a input from javascript callback does not trigger the callback associated with that input

13 Views Asked by At

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)
0

There are 0 best solutions below