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.
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
- 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
- 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);
- 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
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
Great. Glad it’s sorted.
We added anvil.js.await_promise()
for occasions when accessing a JavaScript promise in python.
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.
No, it doesn’t. It only works on limited devices (Mostly Android and Windows).
This is what makes PWAs hard on IOS