I want to disable the input box while it is processing, and to re-enable and return the focus to it when processing is done
This works to disable and re-enable the input box but it loses the focus when disabled and does not get it back when re-enabled. How to return the focus to the point where the user stopped typing?
from dash import Dash, html, callback, Output, Input, dcc
from time import sleep
input_tag = dcc.Input(id='input', debounce=0.500, autoFocus=True)
output_tag = dcc.Input(id='output', disabled=True)
app = Dash(__name__,)
app.layout = [html.Div([input_tag, output_tag]),]
@callback(
Output('output', 'value'),
Input('input', 'value'),
prevent_initial_call=True,
running=[(Output('input', 'disabled'), True, False)]
)
def process(value: str):
sleep(2)
return value
if __name__ == '__main__':
app.run(debug=True)
Hello @clodoaldo,
You will need to leverage the clientside callback and use JS to reset the focus after the callback has run. You’ll need to use a dcc.Store or something to trigger it.
Here the solution, including a spinner. The affected input attribute must be readonly instead of disabled:
from dash import Dash, html, callback, Output, Input, dcc
from time import sleep
import dash_bootstrap_components as dbc
input_tag = dbc.Input(id='input', debounce=500, autoFocus=True)
output_tag = dbc.Input(id='output', disabled=True)
app = Dash(__name__,)
app.layout = [
html.Div([input_tag, dcc.Loading(
children=html.Div(id='spinner_div'),type='circle',)]
, style={'width': 'fit-content'}
),
html.Div([output_tag]),
]
app.clientside_callback(
"""
function(disabled) {
if (disabled === false) {
const el = document.getElementById('input');
if (el) {
el.focus();
}
}
return window.dash_clientside.no_update;
}
""",
Input('input', 'readonly')
)
@callback(
Output('spinner_div', 'children'),
Output('output', 'value'),
Input('input', 'value'),
prevent_initial_call=True,
running=[(Output('input', 'readonly'), True, False)]
)
def process(value: str):
sleep(1)
return '', value
if __name__ == '__main__':
app.run(debug=True)
1 Like