Add to Home Screen on click

Recently, Anvil allowed downloading of anvil apps to the home screen which was a really cool feature. However, is it possible for me to achieve the same with a button click so that when users click on a button, the app will be installed? If you visit anvil forum on mobile, you will be able to see that Anvil has done something like that for themselves as well.

1 Like

Sorry for the delay in this one. There was a piece of missing architecture in anvil.js that would have made this easier. That’s now shipped.

There’s a few ways you can do this and there are a handful of javascript examples out there.
Here’s an anvil solution based on this example: PWA Install Prompt - Jason Ujma-Alvis
As well as documentation from MDN

  1. Optional - use local storage to check if we’ve shown a prompt before
from anvil_extras.storage import local_storage

def get_visited():
  return local_storage.get("seen_prompt")

def set_visited():
  local_storage["seen_prompt"] = True
  1. Add an event handler for the beforeinstallprompt event
from anvil.js import window

install_event = None

def before_install(e):
  global install_event
  e.preventDefault() # stops the default prompt displaying
  if get_visited():
    # don't show the prompt if it's been show
    return
  install_event = e
  get_open_form().show_install_btn()

window.addEventListener('beforeinstallprompt', before_install);
  1. add some logic to the main form
class Form1(Form1Template):

  def show_install_btn(self):
    self.install_prompt_btn.visible = True

  def install_prompt_btn_click(self, **event_args):
    """This method is called when the button is clicked"""
    global install_event
    if install_event is None:
      # sanity check
      self.install_prompt_btn.visible = False
      return
    install_event.prompt()
    
    # install_event.userChoice is a javascript Promise and we wait for the result
    # use anvil.js.await_promise() to do this
    result = anvil.js.await_promise(install_event.userChoice)
    
    if result.get("outcome") == "accepted":
      alert("User accepted the A2HS prompt") # Add To Home Screen (A2HS)
    else:
      alert("User dismissed the A2HS prompt")
    install_event = None
    self.install_prompt_btn.visible = False
    set_visited()

Here’s an example clone link:
https://anvil.works/build#clone:53JPYV6VHWF4FLMI=ORVM4JMIEFLHV6CST4OZLQYX

3 Likes

I am sorry I forgot to update this post but I already figured it out. What was the missing architecture with anvil.js? Because I ran this script which did my job easily

<script>
//In my Native Library
window.addEventListener('beforeinstallprompt', (e) => {
 
  deferredPrompt = e;
});
  
</script>

Then I created a function

<script>
function a2hs() {
  deferredPrompt.prompt();

  // Wait for the user to respond to the prompt
  deferredPrompt.userChoice
    .then((choiceResult) => {
      if (choiceResult.outcome === 'accepted') {
        console.log('User accepted the A2HS prompt');
      } else {
        console.log('User dismissed the A2HS prompt');
      }
      deferredPrompt = null;
    });
}
</script>

https://anvil.works/build#clone:HOB672KDVXDD4CXI=HPIGM6XISA2SGAYXBU65DQ25

1 Like

Great. Glad it’s sorted.

We added anvil.js.await_promise() for occasions when accessing a JavaScript promise in python.

3 Likes

Another nice and helpful feature. Thank you so much for the support.

Where did you put that last part? I dont see it in your clone

In my Native Library

does this work on IOS? I asked because i followed that and nothing happens when i click the button.

1 Like

No, it doesn’t. It only works on limited devices (Mostly Android and Windows).

This is what makes PWAs hard on IOS

3 Likes