Open HyprValent opened 1 year ago
Which version of dash-uploader you are using? Have you tried using the du.callback
instead of the app.callback
?
If you are using version >= 0.7.0, then see this note.
@np-8 Oh I didn't realize the support for @app.callback was removed. I am using a version >= 0.7.0 May I ask how the syntax works for a @du.callback for multiple outputs, similar to the example I gave for @app.callback?
Could you please try:
@du.callback(
output=[Output('callback-output', 'children'),
Output("example-graph2", "figure"),
Output("example-graph3", "figure")],
id="dash-uploader",
)
def callback_on_completion(status: du.UploadStatus):
# your code here
in place of
@app.callback([Output('callback-output', 'children'),
Output("example-graph2", "figure"),
Output("example-graph3", "figure")],
[Input('dash-uploader', 'is_completed'),
Input('dash-uploader', 'n_uploaded')])
def callback_on_completion(is_completed, filecount):
if is_completed and filecount is not None:
# code if the upload is completed
The status
is du.UploadStatus object, where you can find for example status.is_completed
, status.n_uploaded
and other attributes.
It seems to be working, thank you so much! I will close the issue since my problem has now been fixed :)
Reopened the issue to ask how I would go about using multiple inputs in @du.callback, if that's possible?
I'm trying to set up a trigger div so that a specific button component is disabled while files are being uploaded.
Hi @HyprValent, I am not sure if I understand your problem correctly. Could you try to explain a bit more what you are trying to do?
@np-8 In a @du.callback, I have it run some code on the uploaded files. In the app, however, I have an html.Button component that I want only enabled after the @du.callback is finished. So basically, while the callback is executing its code, I want the 'disabled' property of the html.Button to be True and then turn to False when the whole @du.callback is finished.
I'm terribly sorry but I still could not understand the need for the multiple inputs. Anyway, the @du.callback
has always just one input, which is the id of the du.Upload
component. Then, you may have multiple outputs as in regular dash callbacks. Here is what I used to create what you described (as I understood it):
import uuid
import dash_uploader as du
import dash
if du.utils.dash_version_is_at_least("2.0.0"):
from dash import html # if dash <= 2.0.0, use: import dash_html_components as html
else:
import dash_html_components as html
from dash.dependencies import Output, Input
app = dash.Dash(__name__)
UPLOAD_FOLDER_ROOT = r"C:\tmp\Uploads"
du.configure_upload(app, UPLOAD_FOLDER_ROOT)
def get_upload_component(id):
return du.Upload(
id=id,
text="Drag and Drop files here",
text_completed="Completed: ",
cancel_button=True,
pause_button=True,
# max_file_size=130, # 130 Mb
# max_total_size=350,
# filetypes=["csv", "zip"],
upload_id=uuid.uuid1(), # Unique session id
max_files=10,
)
def get_app_layout():
return html.Div(
[
html.H1("Demo"),
html.Div(
[
get_upload_component(id="dash-uploader"),
html.Div(id="callback-output", children="no data"),
html.Button("Create Graphs", id="button", disabled=True),
],
style={ # wrapper div style
"textAlign": "center",
"width": "600px",
"padding": "10px",
"display": "inline-block",
},
),
],
style={
"textAlign": "center",
},
)
# get_app_layout is a function
# This way we can use unique session id's as upload_id's
app.layout = get_app_layout
# 3) Create a callback
@du.callback(
output=[Output("callback-output", "children"), Output("button", "disabled")],
id="dash-uploader",
)
def callback_on_completion(status: du.UploadStatus):
print(status)
files = html.Ul([html.Li(str(x)) for x in status.uploaded_files])
return files, False
if __name__ == "__main__":
app.run_server(debug=True)
and here is the output when uploading
and here is the output after upload is finished:
I don't know if this is what were after, but maybe we can iterate to find a solution for you :)
Okay I think you've almost got what I wanted because that's the code structure I had previously. But say if in the same browser session, I wanted to upload another new file. I would want the button to disable itself again, but there isn't a way to detect the start of another upload to re-disable the button. I'm sorry if I'm not explaining this properly! Let me know if there is a specific part of the question you do not understand.
So did I understand that there are different states of your app:
STATE A:
Uploading data makes state transition A -> B
STATE B:
Clicking the create graphs button makes state transition B -> C
STATE C:
If this is how you want it to work, could there be logic in the callback associated with the "Create graphs" button which would disable the button after it has been clicked?
same as option 1 until here
Clicking the create graphs button makes state transition B -> C
STATE C (Option 2):
Starting upload makes state transition from C -> D
STATE D:
Maybe in this Option 2, you could have in the outputs of the du.callback
also the "disabled" (True or False) property for the button? You could utilize the status.is_completed
for this.
Let me know if this helps you forward!
@np-8 Sorry for the late reply! Yes my implementation in mind is exactly as described in Option 1. The issue is re-disabling the button after the visualization is complete, as you cannot use the same component as an output in two different callbacks. If it isn't too much of an inconvenience, do you have any ideas on how I could go about doing so using @du.callback?
Without going into too much detail, I want to use @app.callback in order to update three different outputs at once the uploading is completely done. This is the structure of the callback so far:
But if I try to run the app, I get the following errors:
How can I use the is_completed and n_uploaded properties in order to run the callback?