I'm trying to create an "Add To Home Screen" button on my progressive web app, as described in Chrome's documentation.
I'm generally following the prescribed pattern, where I have some hidden button which is displayed when Chrome's beforeinstallprompt
event fires.
I capture the event once it fires, and then use the event to begin the native install dialogue once my own install button is clicked. The sample code is below:
let deferredPrompt;
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.
deferredPrompt = e;
// Update UI notify the user they can add to home screen
btnAdd.style.display = 'block';
});
btnAdd.addEventListener('click', (e) => {
// hide our user interface that shows our A2HS button
btnAdd.style.display = 'none';
// Show the prompt
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;
});
});
The issue I'm running into is that I don't want to show my install button (btnAdd
) if the user has already installed the web app to thier home screen, and I'm having trouble figuring out how to check for that scenario.
I was hoping to modify the above code as follows:
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.
deferredPrompt = e;
// If the user has not already installed...
deferredPrompt.userChoice
.then(choiceResult => {
if (choiceResult === undefined) {
// Update UI notify the user they can add to home screen
btnAdd.style.display = 'block';
}
});
});
So that the install button won't be displayed if the user has already installed. But this doesn't seem to work. It appears that if they haven't made a choice already, accessing userChoice
just prompts the user directly with the native dialogue.
I'm not really sure how the beforeinstallevent
works, so this might not even be a good strategy. Ideally I was hoping this would work something like something like navigator.serviceWorker.ready()
, which returns a Promise rather than using browser events to try and figure out when stuff is ready.
In any case, are there any ideas on how I can check that the user has installed to home screen before I show my own home screen install button?
Edit: As Mathias has commented, checking for the event before showing the button should be sufficient. I believe the issue I was having is a result of using localhost, which appears to continually fire the beforeinstallprompt
event even after installation, which is not the intended behavior. Hosting the code solved the issue.