Adding social media share buttons (using Flask-Share) to Dash? Can it be done? Yes it can :)

Hey all

I’m trying to add the Flask-Share social media icons to my Dash app based on this article. Aware this question in general came up in a post last year but no one responded.

The goal is to get something lovely like this in Dash:
Screenshot from 2021-07-03 07-07-28

Code here:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flask-Share Demo</title>
    {{ share.load() }}
</head>
<body>
    <h1>Hello, Flask-Share!</h1>
        <p>Maecenas tincidunt lacus at velit. Phasellus in felis. Praesent
        id massa id nisl venenatis lacinia. Integer ac neque. Morbi ut odio.
        Nullam varius. Sed vel enim sit amet nunc viverra dapibus. Nullam
        varius. In hac habitasse platea dictumst.</p>
        {{ share.create(title='Share with: ') }}
</body>
</html>

I’m aware it can be done in Flask (as above), so the fallback would be to build a proper Flask app with the share icons templated in, and then embed the Dash app.

Is it possible to get this javascript running directly in Dash? I know the html.Script component doesn’t really work. I was hoping to do it cheekily somehow by customising Dash’s HTML template. I’ve tried this but it doesn’t seem to be able to substitute the objects.

Progress so far

Import flask-share and bind it to the underlying flask app

from flask_share import Share
share = Share(app.server)

Attempt to render directly in Dash layout doesn’t work as the script is not executed

 with app.server.app_context():
            component = html.Div([
                html.Div(share.load()),
                html.Div(share.create(title='Share with: '))
            ])

Whilst this runs, it produces the unexecuted JS and outputs this to browser:

<link rel="stylesheet" href="https://cdn.bootcss.com/social-share.js/1.0.16/css/share.min.css" type="text/css"> <script src="https://cdn.bootcss.com/social-share.js/1.0.16/js/social-share.min.js"></script>
<div class="social-share " data-sites="weibo, wechat, douban, facebook, twitter, google, linkedin, qq, qzone" data-mobile-sites="weibo, douban, qq, qzone" align="left">Share with: </div>

Obviously I want to somehow get this script to execute in Dash, but I’m not sure how. Then I thought I could get smart and embed it in the Dash HTML template, as per the Flask example, like so:

from flask_share import Share
app = dash.Dash(__name__)
share = Share(app.server)

app.index_string = '''

<html>
    <head>
        {%metas%}
        <title>{%title%}</title>
        {%favicon%}
        {%css%}
        {{ share.load() }}
    </head>
    <body>
        <div>My Custom header</div>
        {%app_entry%}
        <footer>
            {%config%}
            {%scripts%}
            {%renderer%}
        </footer>
        <div>My Custom footer</div>
        {{ share.create(title='Share with: ') }}
    </body>
</html>
'''

But this just outputs the text string and does not substitute the share object and execute the script. I don’t really know what I’m doing with javascript and web so this is very hard for me. I tried a few variations of substitution like {blah} {{blah}} {%blah%}

Am I going down the path to madness and should I give up and just build a proper underlying Flask app, or is there a way I could get flask-share somehow running in Dash itself??

Cheers

Oh my *** I think I have done it. This is the dodgiest work around ever, but it seems to be working.

So I copied the actual snippet that the Share tries to execute from flasks-share
<link rel="stylesheet" href="https://cdn.bootcss.com/social-share.js/1.0.16/css/share.min.css" type="text/css"> <script src="https://cdn.bootcss.com/social-share.js/1.0.16/js/social-share.min.js"></script>
<div class="social-share " data-sites="weibo, wechat, douban, facebook, twitter, google, linkedin, qq, qzone" data-mobile-sites="weibo, douban, qq, qzone" align="left">Share with: </div>

And I just banged it into the Dash HTML template manually:

app.index_string = '''

<!DOCTYPE html>
<html>
    <head>
        {%metas%}
        <title>{%title%}</title>
        {%favicon%}
        {%css%}
        <link rel="stylesheet" href="https://cdn.bootcss.com/social-share.js/1.0.16/css/share.min.css" type="text/css"> 
        <script src="https://cdn.bootcss.com/social-share.js/1.0.16/js/social-share.min.js"></script>
    </head>
    <body>
        <div>My Custom header</div>
        {%app_entry%}
        <footer>
            {%config%}
            {%scripts%}
            {%renderer%}
        </footer>
        <div>My Custom footer</div>
        <div class="social-share " data-sites="weibo, wechat, douban, facebook, twitter, google, linkedin, qq, qzone" data-mobile-sites="weibo, douban, qq, qzone" align="left">Share with: </div>
    </body>
</html>
'''

And voilla…it seems to work!
Screenshot from 2021-07-03 07-37-54

Someone please tell me if this is a very stupid thing to do, or if this will be reasonably robust.

I think that is the standard way to do it :slight_smile:

1 Like

Thanks Emil. I am very new to this.

A quick followup questions: now that I have my share icons, they work fine as far as I can tell BUT they only share the domain and not the full path.

Really my goal is to be able to share the full URL pathname the user is on, rather than just the raw domain. This is available as dcc.Location in the dash app, but I’m not actually sure that the underlying Flask app can access this and/or if there would be a way to inject that into the path that the social media icons use…

Any thoughts on how I might do this??

Objective: share full URL path via social media icons baked into the Dash HTML index template.

Just for closure, FYI to anyone who may wish to add social media share icons to their dash site. I’ve found a pretty straight forward way using a different javascript library. This is now working beautifully for dynamically updated page titles and URL paths.

I ended up using https://shareon.js.org/
Opensource and super light weight.

Screenshot from 2021-07-06 14-02-01

How to do it…

Step 1 - update the Dash index.html template
This allows you to import the javascript and insert the <a> components in for the icons. You can do this in your main dash python file. More info here and scroll down to ’ Customizing Dash’s HTML Index Template’

Working example here:

app.index_string = '''
<!DOCTYPE html>
<html>
    <head>
        {%metas%}
        <title>{%title%}</title>        
        {%favicon%}
        {%css%}        
        
        <link href="https://cdn.jsdelivr.net/npm/shareon@1/dist/shareon.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/shareon@1/dist/shareon.min.js" type="text/javascript"></script>
        
    </head>
    <body>        
        {%app_entry%}
        <footer>
            {%config%}
            {%scripts%}
            {%renderer%}           
        </footer>  
                
        <div style="overflow:hidden;width:40%;margin:auto;padding-top:10px">
            <H3 style="float:left;padding-top:5px"> Share on: </H3>
            <div class="shareon" style="overflow:hidden;width:600px;margin:auto;text-align:left">  
                <a class="twitter"></a>    
                <a class="facebook"></a>
                <!-- FB App ID is required for the Messenger button to function -->
                <!--  <a class="messenger" data-fb-app-id="0123456789012345"></a> -->
                <a class="linkedin"></a>
                <a class="reddit"></a>
                <a class="mastodon" data-text="Check this out!"></a>                
                <a class="odnoklassniki"></a>
                <a class="pinterest"></a>
                <a class="pocket"></a>
                <a class="vkontakte"></a>
                <a class="viber" data-text="Check this out!"></a>                
                <a class="telegram "data-text="Check this out!"></a>
                <a class="whatsapp" data-text="Check this out!"></a>            
            </div>
        </div>
        
        </body>
</html>
'''

Step 2 - Add a clientside javascript callback to refresh the icons
If you just want the icons to contain static text and URL paths, then you can hardcode these into the components themselves in the HTML in step 1, using the attributes ‘data-title’ and ‘data-url’ as documented on https://shareon.js.org/

But, if you want to do something a bit more sophisticated and share dynamic content like updated page title and URL path, you will need a clientside callback and pass in the data.

  app.clientside_callback(                        
        """
        function(label) {          
            document.title = 'New page title : ' + label;
            shareon();            
        }
        """,
        Output('js-social-share-dummy', 'children'),        
        Input('js-social-share-refresh', 'children'),        
        prevent_initial_call=True
    )    

In this case, I trigger the callback when I updated my dcc.Location. I also pass in the new page title (label). When the shareon() function is called, it refreshes all the icons with the new title and current URL path set by dcc.Location.

So confirming you don’t need flask-share at all and you can do everything you need with javascsript.

Cheers
Dan

1 Like