loading...

How to implement the Web Share API with a fallback

daviddalbusco profile image David Dal Busco Updated on ・5 min read


Photo by Noiseporn on Unsplash

In the past weeks I often had to implement the Web Share API in several applications. As it is not yet supported by all browsers and devices, I always had to implement the same fallback, respectively I always used the open source Web Component I developed called “Web Social Share” as a fallback. That’s why I’m sharing my solution with this new blog post, hoping that maybe someday it will help someone or even better, that maybe someone will ping me back with a better solution 😁

Getting started

The following implementation is pretty straight forward. We are going to implement a share method which detects if the Web Share API is supported by the browser or not. If supported it will, I guess you get it, use and open the Web Share API otherwise it will open the share fallback.


Safari (left) supports Web Share API, Chrome (desktop, right) doesn’t support it and fallback to the Web Component “Web Social Share”

Main function and detection

First, we are going to implement a main share function which checks which share method should be use.

<script language="JavaScript">
  openShare = async () => {
    if (navigator && navigator.share) {
      await shareNative();
    } else {
      await shareFallback();
    }
  };
</script>

Web Share API

We are now going to implement the above method called shareNative() which will use the Web Share API.

This API accepts three parameters currently: url , text and title . Only one of these parameters should at least be provided but I suggest you to use text and url . Using these two will for example allow you to add a nice message when a user would share an URL on Twitter.

The Web Share API is promised based and we are going to implement it like the following:

function shareNative() {
  return new Promise(async (resolve) => {
    const shareUrl =
          `${window.location.protocol}//${window.location.host}`;

    await navigator.share({
      text: 'How to implement the Web Share API and a fallback',
      url: shareUrl,
    });

    resolve();
  });
}

We are using window.location to build dynamically the url we are going to share. You could replace this piece of code with any valid URL as a string if you rather like.

Web Social Share as Fallback

The Web Component I developed need firstly to be consumed. You could install it through npm but in this tutorial we are just going to use it with the help of Unpkg. For that purpose, we are going to add the following scripts to our HTML page:

<script type="module"
    src="https://unpkg.com/web-social-share@latest/dist/websocialshare/websocialshare.esm.js"></script>
<script nomodule 
    src="https://unpkg.com/web-social-share@latest/dist/websocialshare/websocialshare.js"></script>

The component doesn’t ship any icons respectively we will have to provide our own. I designed the component that way because I thought that it makes more sense to not “force” the developer to use an icon which might not fits its design. Therefore, in this tutorial, we are going to use the Ionicons which we are going to consume using Unpkg too. Of course, if your application already contains its own set of icons, just skip this step.

<script src="https://unpkg.com/ionicons@latest/dist/ionicons.js"></script>

Declaration

In opposition to the Web Share API, this component can’t guess which methods are available on the device where it runs. That’s why it only exposes a couple of share methods. In this tutorial we are going too implement the options Email, Twitter and WhatsApp.

To declare the component we are going to add it to the page, specifying that per default it should not be displayed ( show="false" ). We are also going to specify the icons we want to use. Note that these are passed to the component using slot and could be inline styled.

<web-social-share show="false">
  <ion-icon name="logo-twitter" ariaLabel="Twitter" slot="twitter"
            style="color: #00aced;">
  </ion-icon>
  <ion-icon name="mail" slot="email" ariaLabel="Email" 
            style="color: #ff8ea3;">
  </ion-icon>
  <ion-icon name="logo-whatsapp" ariaLabel="WhatsApp"
            slot="whatsapp"
            style="color: #25D366;">
   </ion-icon>
</web-social-share>

If you never use slot before and want to know a bit more about them, I wrote another article “A practical introduction to styling a Shadow DOM and Slots” which tries to explain practically how these could be used and styled.

Implementation

Now that we have consumed and declared the Web Component, we just have to implement the final piece with the implementation of the above mentioned method called shareFallback().

This function will query the DOM for a reference on the component (using document.querySelector ), define the share options and finally will trigger the display of the share options by modifying its show attribute (the component listen for changes on this attribute to display or not its toolbar).

function shareFallback() {
  return new Promise(async (resolve) => {
    const webSocialShare =
          document.querySelector('web-social-share');

    if (!webSocialShare || !window) {
      return;
    }

    const shareUrl =
          `${window.location.protocol}//${window.location.host}`;

    const share = {
      displayNames: true,
      config: [{
        twitter: {
          socialShareUrl: shareUrl,
          socialSharePopupWidth: 300,
          socialSharePopupHeight: 400
        }
      },{
        email: {
          socialShareBody: shareUrl
        }
      }, {
        whatsapp: {
          socialShareUrl: shareUrl
        }
      }]
    };
    // The configuration, set the share options
    webSocialShare.share = share;
    // Show/open the share actions
    webSocialShare.show = true;

    resolve();
  });
}

That’s it, we have implemented the Web Share API and a fallback 🎉

Trying it out

To try out the implementation, we could just add for example a button which calls openShare() when its clicked.

<button onClick="openShare()">Share</button>

If everything went according plan, the result should looks like the following:


Again, Safari (left) supports Web Share API and Chrome (desktop) doesn’t and use the fallback

Cherry on the cake 🍒🎂

Like I said in my introduction, I implemented the above solution in several applications the past weeks, I notably implemented it in the website and starter kit of DeckDeckGo, our upcoming open source web editor for presentations. Therefore don’t hesitate to have a look at the code and to ping me if you have a better solution to share or maybe even have a PR to submit to improves it 😉

To infinity and beyond 🚀

David

Posted on Apr 10 by:

daviddalbusco profile

David Dal Busco

@daviddalbusco

Creator of DeckDeckGo | Organizer of the Ionic Zürich Meetup

Discussion

markdown guide
 

we (a few weeks back) use something similar to

  • web share if supports
  • else copy to cliboard if supports
  • tell the user to copy manually
 

good solution too!

what do you use for the copy to clipboard? it's maybe actually a good idea too to add it as a default option of my fallback web component

 

cool cool cool, thx 👍

Really like it, so I implemented that idea and published it in my component straight away 😃

websocialshare.com

 

I recently tried to use API to React without knowing nothing about Promise or nor XMLHttpRequest. I faced a bunch of pending promise returns and a bit panicked. I definitely have to study this topic.

 

It took me a couple of practice to use promises and async/await concept but once used to it, I use promises almost everywhere now.

Never tried React though, there is always something new to learn for everyone ;)

 

I also just started. But I feel like I have to study JS more in the first place. The fact that there are only more things to learn is both glad and fearful.