Hi!
I have a dash app where I am uploading figure(s) and adding a figure caption for each figure. I am storing this data and then using them in another callback to add to a pdf page and eventually save as a pdf. I have a button to click to remove a figure and change that button to a red button when it is clicked.
Issue: When I am trying to add figures in a separate upload, it overrides the previous images. Additionally, if I delete an image and try to upload another figure to replace it, it will keep the index of the removed figure, therefore removing the newly uploaded figure because it uses the same id.
What I want the code to do: Keep all the images (and captions) and list them that are uploaded unless they are selected to remove.
What I’ve tried: I’ve tried to use a unique id instead of index (uid), create lists of all the figures and captions and remove them deliberately. I also tried to have separate callbacks for all of them (along with changing input/state) and having the lists out of the for loop.
Versions of the packages:
dash: 3.0.4
dcc: 3.0.6
html: 3.0.2
dash_table: 6.0.2
(I’ve tried to update to dash 3.1, but it hasn’t updated… even though it says it updated the packages and the license was updated)
What I have currently for the code:
def parse_contents_extra( filename):
return( filename+'\n')
def parse_contents(contents, filename, date,title):
if title[0] == 'Extra Pictures':
return(title[0]+': '+ filename[0]+'\n')
else:
return(title[0]+': '+ filename)
@callback(
Output('output-image-extra', 'children',allow_duplicate=True),
#Input('upload-image-extra', 'contents'),
Input('upload-image-extra', 'filename'),
prevent_initial_call=True)
def update_output_extra(list_of_filenames):
image_blocks = []
if list_of_filenames is not None:
for i, fig_name in enumerate( list_of_filenames):
#names_extra_all.append(fig_name)
parsed_contents = parse_contents_extra(fig_name)
image_block = html.Div([parsed_contents,
dcc.Input(id={'type': 'caption-input', 'index': i}, type='text',
placeholder='Enter caption for ' + fig_name, style={'width':'90%'}),
html.Button('X',id={'type': 'rm-picture', 'index': i}, style=default_button_style)])
image_blocks.append(image_block)
return(image_blocks)
@callback(Output('caption-store', 'data'),
Output('filename-store', 'data'),
Output({'type': 'rm-picture', 'index': ALL}, 'style', allow_duplicate=True),
Input({'type': 'rm-picture', 'index': ALL}, 'n_clicks'),
Input({'type': 'caption-input', 'index': ALL}, 'value'),
State('upload-image-extra', 'filename'),
prevent_initial_call=True)
def rm_pictures(nclicks, captions, filenames):
print('rm')
ctx = dash.callback_context
style = []
# Copy the inputs so we can safely modify
updated_captions = list(captions)
updated_filenames = list(filenames)
clicked_index = ctx.triggered_id['index']
for click in nclicks:
if click is not None:
index = ctx.triggered_id['index']
#list_of_contents.pop(index)
updated_captions.pop(index)
#caption_list = captions
updated_filenames.pop(index)
#names_extra_all.pop(index)
style.append(red_button_style )
else:
style.append(default_button_style)
return(updated_captions, updated_filenames, style)
@callback([Output('download-pdf','children')],
[Input('save-pdf-button','n_clicks'),
Input('unit-selection','value'),
State('caption-store','data'),
State('filename-store','data')], prevent_initial_call=True)
def update_output(nclicks,units,captions,filenames_store,extra_file):
if len(filenames_store) > 1:
#print(captions, names_extra_all)
pdf.cell(200,5, text='Extra Pictures', align='C')
for file, caption in zip(filenames_store, captions):
figure = figure_path+file
pdf.image(figure,x=20,y=20,w=width_extra, keep_aspect_ratio=True)
pdf.ln()
pdf.write(5,text = caption)
pdf.add_page()
if len(filenames_store) == 1:
#print(captions, names_extra_all)
extra_figure = figure_path+filenames_store[0]
pdf.cell(200,5, text='Extra Pictures', align='C')
pdf.image(extra_figure,x=20,y=20,w=width_extra, keep_aspect_ratio=True)
pdf.write(5, text=captions[0])
Image showing three figures uploaded and the captions added. There is a red button indicating that figure was deleted.
I hope this isn’t too confusing. Please let me know if you need any clarification on anything or need other information! I haven’t found any questions about this, but if you know of one that covered something similar, please let me know!
Thank you so much!
