Hello,
I present a simple example for downloading a component as an image using clientside_callbacks. We achieve this by using the dom-to-image javascript function.
I wanted to display the filters and a message alongside the graph for sharing purposes. Prior to this, I found users were sharing the graphs they created but not including the filters they applied to the data being shown. I initially tried this using html2pdf; however 1) the users prefer images for sharing and 2) the pdf kept cutting off and I couldn’t get it debugged properly. I finally found dom-to-image which made doing this a lot easier.
Here is how I implemented it:
- Add the dom-to-image function to our external scripts (link to cdn in code), or download and serve it locally.
- Create button with
id=download-image
- Create a component with `id=‘component-to-save’
- Define a
clientside_callback
when the button is clicked - Call the following function:
function(n_clicks){
if(n_clicks > 0){
domtoimage.toBlob(document.getElementById('component-to-save'))
.then(function (blob) {
window.saveAs(blob, 'download.png');
}
);
}
}
Full example:
import dash
from dash import html, clientside_callback, Input, Output
import dash_bootstrap_components as dbc
app = dash.Dash(
__name__,
external_stylesheets=[dbc.themes.BOOTSTRAP],
external_scripts=[
{'src': 'https://cdn.jsdelivr.net/npm/dom-to-image@2.6.0/dist/dom-to-image.min.js'}
]
)
app.layout = html.Div(
[
html.H1('Title of the page'),
html.P('The outside of the card is not saved.'),
dbc.Button(
'Download as image',
id='download-image'
),
dbc.Card(
'Everything in here is downloaded as an image',
body=True,
id='component-to-save'
)
]
)
clientside_callback(
"""
function(n_clicks){
if(n_clicks > 0){
domtoimage.toBlob(document.getElementById('component-to-save'))
.then(function (blob) {
window.saveAs(blob, 'download.png');
}
);
}
}
""",
Output('download-image', 'n_clicks'),
Input('download-image', 'n_clicks')
)
if __name__ == "__main__":
app.run_server(debug=True)
I hope this helps!
Brad