How to add an Add to Homescreen button in your PWA
Tags: pwa, javascript, vue
Published: 2021-07-02 04:23:09

## Introduction
As of 2021, PWA features are supported to varying degrees by Google Chrome, Apple Safari, Firefox for Android (not desktop), and Microsoft Edge. This means your PWA can be installed as an app on all modern mobiles and desktops. 

This makes PWAs very powerful as a single code base can be used across variety of devices without the need for varied configurations to support different environments (looking at you flutter).

This article will show you how to solve the issue of adding an Add to Homescreen button to your PWA which can show the user a prompt to install your app when required. 

This tutorial is using VueJS, but you can use the same code anywhere.


### Problem
The Add to Homescreen popup shows up on page load rather than when required.

### Solution
Capture the event, store it and show it as required.

### Code
We make a component `addToHomeBtn.vue` which is imported in the **entry point** of your app. `App.vue` in this case.

Start by creating a variable to store the event, so it can be used later:
```js
data(){
  return {
   deferredPrompt: null,
  }
 }
```

Now add the method to capture the event:
```js
captureEvent() {
      window.addEventListener('beforeinstallprompt', (e) => {
        // Prevent Chrome 67 and earlier from automatically showing the prompt
        e.preventDefault()
        // Stash the event so it can be triggered later.
        this.deferredPrompt = e
      })
    }
```

And now simply call this method in the mounted hook of the component.

```js
mounted() {
    this.captureEvent()
  }
```

To re-invoke the prompt, simply use the event we stored before.

```js
clickCallback() {
      // Show the prompt
      this.deferredPrompt.prompt()
      // Wait for the user to respond to the prompt
      this.deferredPrompt.userChoice.then((choiceResult) => {
        if (choiceResult.outcome === 'accepted') {
          // Add analyticcs event
          this.$gtag.event('add_to_home_screen')
        }
        this.deferredPrompt = null
      })
    }
```
```html
<button
     v-if="deferredPrompt"
     ref="addBtn"
     class="add-button"
     @click="clickCallback"
>
     Add
</button>
```

And, that's done! 
#### Full Component Code

```html
<template>
  <div>
    <button
      v-if="deferredPrompt"
      ref="addBtn"
      class="add-button"
      @click="clickCallback"
    >
      Add
    </button>
  </div>
</template>

<script>
export default {
  name: 'AddToHomeScreen',
  data: () => ({
    deferredPrompt: null,
  }),
  mounted() {
    this.captureEvent()
  },
  methods: {
    captureEvent() {
      window.addEventListener('beforeinstallprompt', (e) => {
        // ! Prevent Chrome 67 and earlier from automatically showing the prompt
        e.preventDefault()
        // Stash the event so it can be triggered later.
        this.deferredPrompt = e
      })
    },
    clickCallback() {
      // Show the prompt
      this.deferredPrompt.prompt()
      // Wait for the user to respond to the prompt
      this.deferredPrompt.userChoice.then((choiceResult) => {
        if (choiceResult.outcome === 'accepted') {
          // Call another function?
        }
        this.deferredPrompt = null
      })
    },
  },
}
</script>
```
The primary part of the code is pure JS and can be used anywhere. Just make sure you call the event before browser shows the prompt.

Thanks for reading!