2

Dear readers,

I want to display an image on a Python Dash page that is generated by some JS code. See the description here: https://www.altmetric.com/assets/Getting_Started_Altmetric_Badges.pdf. In a static HTML page one would include this script

<script type='text/javascript' src='https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js'></script>

and this DIV will show the image:

<div class='altmetric-embed' data-badge-type='donut' data-doi="10.1038/nature.2012.9872"></div>

Im trying to get this working in Dash but not even once the image/badge is shown. I tried several options for injecting te DIV (with dash_dangerously_set_inner_html.DangerouslySetInnerHTML() or with the attributesd of DIV using '**{'), and including the SCRIPT (in the custom HEAD of the var index_string, as Html.Script(), as external_scripts and with options serve_locally = False/True), but none seems to work. Good to mention is that Dash serves me a page with only the "Hello World" string but without any images. But when I locally store the generated HTML code to a HTML file and open it in my browser, the images are shown !

Localhost gives me: this view, whereas the same page gives me locally: this view

See included (minimal) non-working example.

Any suggestions here ?

Kind regards, IvoB

#SEE: https://www.altmetric.com/assets/Getting_Started_Altmetric_Badges.pdf
import dash
import dash_dangerously_set_inner_html
import dash_html_components as html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
external_scripts = ['https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js']
app = dash.Dash(__name__, external_scripts=external_scripts, external_stylesheets=external_stylesheets)
app.css.config.serve_locally = False
app.scripts.config.serve_locally = False

app.index_string = '''
<!DOCTYPE html>
<html>
    <head>
        <script type='text/javascript' src='https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js'></script>
        {%metas%}
        <title>{%title%}</title>
        {%favicon%}
        {%css%}
    </head>
    <body>
        <div>My Custom header</div>
        {%app_entry%}
        <footer>
            {%config%}
            {%scripts%}
            {%renderer%}
        </footer>
        <div>My Custom footer</div>
    </body>
</html>
'''

app.layout = html.Div([
    html.Script(src='https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js'),
    html.Div('Hello world'),
    html.Div(dash_dangerously_set_inner_html.DangerouslySetInnerHTML("<div class='altmetric-embed' data-badge-type='donut' data-doi='10.1038/nature.2012.9872'></div>")),
    html.Div(className='altmetric-embed', **{'data-badge-type' : 'donut', 'data-doi' : '10.1038/nature.2012.9872'})
])

if __name__ == '__main__':
    app.run_server(debug=True)
1
  • I think the JS script is getting blocked because of CORS. Commented Apr 4, 2021 at 23:14

1 Answer 1

1

The problem is that Dash hasn't finished rendering the altmetric div yet so the script doesn't act on it.

If you put

<div class='altmetric-embed' data-badge-type='donut' data-doi='10.1038/nature.2012.9872'></div>

inside the body of the index_string you will notice that the badge does show up.

If you want the div in the dash layout to work with the script you could use something like dash_defer_js_import to defer execution of the altmetric script.

You can install it with:

pip install dash_defer_js_import

and use it like this:

import dash
import dash_html_components as html
import dash_defer_js_import as dji

app = dash.Dash(__name__)

app.layout = html.Div(
    [
        html.Div(
            className="altmetric-embed",
            **{"data-badge-type": "donut", "data-doi": "10.1038/nature.2012.9872"}
        ),
        dji.Import(src="https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js"),
    ]
)


if __name__ == "__main__":
    app.run_server()

For better understanding what this Import component is doing you can look at the source code here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.