Hi Chris,
I’m not sure if this helps, but I wanted to give users an option to download the interactive Plotly graphs. As Emil mention, this isn’t the interactivity I have included with Dash, but rather the interactivity in the Plotly Figures themselves (with any buttons you included in the FIgures).
Here’s a function that takes a figure list, stores it in the buffer and associates it with a button. While this might not be exactly what you’re looking for, hopefully it’ll be a starting point.
Note: My Dash app has a lot of tabs and I was using this as an optional download for the users. I found that my tabs rendered about 40% faster without this button, and ended up removing it. However, my app has a lot of figures on each tab, and many datapoints per Figure. The extra load time may not be an issue for others.
import io
from base64 import b64encode
def create_html_download_button(figs, file_name="plotly_graph", button_name="Download as HTML"):
"""
Given a Plotly Figure or list of Plotly Figures, stores that in a buffer and returns a button (div.A) object that downloads the figure as an HTML file when clicked.
:param figs: Plotly Figure or List of Plotly Figures
:param file_name: String (name of file to download >> '.html' will be appended)
:param button_name: String (text to display on the button)
:return: Dash dbc.Button object
"""
# Special handling of storing multiple figures in buffer.
if isinstance(figs, list) and len(figs) > 1:
# keep non-None figs
figs = [fig for fig in figs if fig != None]
# Create buffer
main_buffer = io.StringIO()
outputs = []
# Write First figure w/ full HTML and add to list
_buffer = io.StringIO()
figs[0].write_html(_buffer, full_html=True, include_plotlyjs='cdn')
outputs.append(_buffer)
# Write remaining figs as divs and append to output list
for fig in figs[1:]:
_buffer = io.StringIO()
fig.write_html(_buffer, full_html=False)
outputs.append(_buffer)
# CONCAT list into main output
main_buffer.write(''.join([i.getvalue() for i in outputs]))
else:
# Create buffer
main_buffer = io.StringIO()
# Write figure to buffer
if isinstance(figs, list):
figs[0].write_html(main_buffer)
else:
figs.write_html(main_buffer)
# Convert buffer to bytes and encode/decode
html_bytes = main_buffer.getvalue().encode()
encoded = b64encode(html_bytes).decode()
# CREATE dbc Button
download_html = dbc.Button(button_name, href="data:text/html;base64," + encoded, download=file_name + ".html")
# Return the Export HTML button
return download_html
While multiple dropdowns are possible, they generally don’t interact like most people want them to. To add multiple dropdowns, just add two “buttons” to your updatemenus. Here’s a snapshot of how you might build your updatemenus for this:
updatemenus = [dict(type="dropdown", buttons=your_1st_dropdown, direction='down', active=0, x=.98), dict(type="dropdown", buttons=your_2nd_dropdown, direction='down', x=.88)]