Hello! I have a button that runs a function that performs a request and returns a file. This can take some time.
I would like to dynamically disable the button when I press it and enable it automatically when function returns the file.
I’m able to disable and enable it programatically, but I’m not having the desired behavior: the button keeps enabled during the request and is disabled after the file is returned.
Button is declared like this:
html.Div([
dbc.Button(
"Generate pdf file",
id=f"{PAGE_ID}_export_button",
color='success',
disabled=False,
outline=True
),
dcc.Download(id=f"{PAGE_ID}_download-pdf")
])
And I declared 2 callbacks, one for disabling button when it’s pressed, and another for processing and re-enabling button:
@app.callback(
Output(f"{PAGE_ID}_export_button", "disabled"),
[Input(f"{PAGE_ID}_export_button", "n_clicks")])
def disable(n_clicks):
changed_id = [p['prop_id'] for p in callback_context.triggered][0]
if changed_id != f"{PAGE_ID}_export_button.n_clicks":
return no_update
if n_clicks is None:
return no_update
return True
@app.callback(
[Output(f"{PAGE_ID}_download-pdf", "data"),
Output(f"{PAGE_ID}_export_button", "disabled")],
Input(f"{PAGE_ID}_export_button", "n_clicks"),
[State(f"{PAGE_ID}_labelsperserial", "value"),
State(f"{PAGE_ID}_offsetlines", "value"),
State(f"{PAGE_ID}_filename", "value"),
State(f"{PAGE_ID}_start", "value"),
State(f"{PAGE_ID}_devicetype", "value"),
State(f"{PAGE_ID}_batchname", "value"),
State(f"{PAGE_ID}_batchsize", "value"),
State(f"{PAGE_ID}_revision", "value")],
prevent_initial_call=True)
def download_pdf(n_clicks, labelsperserial, offsetlines, filename, start, devicetype, batchname, batchsize, revision):
changed_id = [p['prop_id'] for p in callback_context.triggered][0]
if changed_id != f"{PAGE_ID}_export_button.n_clicks":
return [no_update, False]
if n_clicks is None:
return [no_update, False]
fn = filename
if fn is not None and not fn.endswith(".pdf"):
fn = fn + ".pdf"
response = requests.get(
base_url + f"/labels/generate-microscopes-serial-sheet?labelsperserial={labelsperserial}&offsetlines={offsetlines}" +
f"&filename={filename}&start={start}&devicetype={devicetype}&batchname={batchname}&batchsize={batchsize}&revision={revision}",
)
return [dcc.send_bytes(response.content, fn, type="application/pdf"), True]
What I’m doing wrong?
Thanks for any ideas!