Black Lives Matter. Please consider donating to Black Girls Code today.

Accessing a new component generated in a callback

I have a dcc.Dropdown(id='my-options') with options ‘A’ and ‘B’. If pressing option ‘A’ the callback will return a dcc.Upload(id='upload-data') component in an existing html.Div(id='file-upload-goes-here').

This seems to work fine, when selecting option ‘A’, a file upload area pops up in the html.Div(id='file-upload-goes-here'). However, the callback listning for the dcc.Upload(id='upload-data') does not get triggered.

First I got the following error:

If you are assigning callbacks to components
that are generated by other callbacks
(and therefore not in the initial layout), then
you can suppress this exception by setting
`app.config['suppress_callback_exceptions']=True`.

Since the dcc.Upload(id='upload-data') is generated by another callback I suppressed this exception. Still without any luck of accessing the uploaded file in dcc.Upload(id='upload-data'). I can select files, so the Upload component is working, but once a file is uploaded I hope that the callback will be triggered since dcc.Upload(id='upload-data') has changed.
Relevant code inside app.layout;

html.Div(dcc.Dropdown(id='my-options', options=[{'label': 'A', 'value': 'A'}, {'label': 'B', 'value': 'B'}])),
html.Div(id='file-upload-goes-here'),
html.Div(id='uploaded-file-preview')],

Corresponding callbacks;

@app.callback(
    Output(component_id='file-upload-goes-here', component_property='children'),
    [Input(component_id='my-options', component_property='value')],
)
def dropdown_options(option):
    if option == 'A':
        return dcc.Upload(
            id='upload-data',
            children=html.Span([
                'Drag and Drop files or ',
                html.A('Upload')
            ]),
            multiple=True
        )
    else:
        return None

Callback for the generated component dcc.Upload(id='upload-data');

@app.callback(
    Output(component_id='uploaded-file-preview', component_property='children'),
    [Input(component_id='upload-data', component_property='value')],
)
def uploaded_files(files):
    # Help!
    # THIS DOES NOT GET TRIGGERED!
    print('input of file upload:', files)

TLDR;
Cannot access a component generated in another callback. Therefore I cannot access files that is uploaded.

Help is appreciated!

I think this is because in your second callback you should be listening to the ‘contents’ property of ‘upload-data’ not ‘value’?

Yep, that’s the culprit!