JS BeforeUnload Event Listener
To prevent the lost of unsaved changes, JavaScript offers the beforeunload event handler. It is executed before the current page is left through navgition by history or links. In older browser versions, it was possible to set a customized text, but nowadays it is enough to call a classic event.preventDefault() to trigger the alter window:
if (edited) {
window.addEventListener('beforeunload', () => {
event.preventDefault();
});
}
In reactive frameworks (like Vue.js) the page and especially the JS logic isn't reloaded in the classical sense. They "mimic" the native HTTP logic and only reload the necessary parts - that's their concept. So we also need to bind or function to routing changes within the framework with the onMounted() and onUnmounted() functions:
onMounted(() => {
window.addEventListener('beforeunload', handleBeforeUnload)
});
onUnmounted(() => {
window.removeEventListener('beforeunload', handleBeforeUnload);
});
We also want to mimic the alert window the loss prevention when navigation with the Vue app, so we set a onBeforeRouteLeave() hook and trigger the alert with the default Firefox text:
onBeforeRouteLeave(() => {
const answer = window.confirm('This page is asking you to confirm that you want to leave — information you’ve entered may not be saved.');
return !answer;
});
Finally, I put all together in a reusable composable:
import {onMounted, onUnmounted, ref} from 'vue';
import {onBeforeRouteLeave} from "vue-router";
const edited = ref(false);
const confirmText = 'This page is asking you to confirm that you want to leave — information you’ve entered may not be saved.';
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
if (edited.value) {
event.preventDefault();
}
}
export function useEdit() {
onMounted(() => {
window.addEventListener('beforeunload', handleBeforeUnload)
});
onUnmounted(() => {
window.removeEventListener('beforeunload', handleBeforeUnload);
});
onBeforeRouteLeave(() => {
if (edited.value) {
const answer = window.confirm(confirmText);
if (!answer) {
return false;
}
edited.value = false;
}
});
return { edited };
}
References
- Window: beforeunload event (MDN) - https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event