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)
Great. this works. Does this also works for dcc.Store. So, instead of changing a value in the input field, i want to change the value in dcc.Store from clientside_callback and that chhange should trigger a dash callback
This should work for anything that is controlled by Dash, the key being that it has to be defined with an id. This will also work for anything that doesnt currently exist in the DOM. (Modals, popovers, etc)
But such tasks can come from external source. I want to display them in the same output_result.
With get_props I would run some javascript likt
more_tasks = [task1, task2,...]
children = get_props('output_result', 'children')
children = [...children, ...more_tasks]
set_props('output_results', {children:children})
Right now I don’t know how to do that in the same output_results. So I should create ‘output_results_external’ by raw javascript, and later add children by raw javascript.