Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Upload attributes not cleared after callback runs (related to #816?) #818

@hartzell

Description

@hartzell

I have a callback that is responsible for adding or removing "jobs" from a list.

It has two inputs and a state. The first input is an Upload, if it is not None then the files are added to the list of jobs. The second input is a button and the state is the value of a Dropdown with multi set to true. If the button is pressed then the jobs from the Dropdown are removed from the list.

When a file is dropped into the Upload, the callback fires and the file is added to the list of jobs.

When the button is pressed, it turns out that the previously uploaded filename is still present in the filenames Input variable so it ends up getting re-added. If that file had been chosen for deletion then it is both deleted and added, resulting in no-change. If a different file had been chosen for deletion that the first file is added to the list again, resulting in a duplication.

I can work around this by checking the context to see what triggered the callback, rather than depending on the state of the Input variables.

I AssUMe-ed that once the callback ran the Inputs/States related to the Upload would be cleared or reset or .... Am I mistaken?

It's possible that this also explains Issue #816; perhaps the Upload component or Dropzone is seeing a file that is the same as the current contents of those variables and therefor does nothing.

There is a full example of this behavior in this gist. Here's the callback:

@app.callback(
    Output("jobs", "data"),
    [
        Input("upload-data", "filename"),
        Input("delete-jobs-button", "n_clicks"),
    ],
    [State("jobs-to-delete", "value"), State("jobs", "data")],
)
def update_jobs(new_jobs, button, delible_jobs, jobs):
    ctx = dash.callback_context
    print("---")
    print(f"ctx.triggered: {ctx.triggered}")
    print(f"Delible: {delible_jobs}")
    print(f"New: {new_jobs}")
    print(f"Jobs: {jobs}")

    if new_jobs is None and delible_jobs is None:
        raise PreventUpdate

    jobs = jobs or []
    if delible_jobs is not None:
        jobs = [j for j in jobs if j not in delible_jobs]

    if new_jobs is not None:
        jobs += new_jobs
    return jobs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions