How do I warn a user of unsaved changes before leaving a page in Vue
Asked Answered
G

4

46

I have an UnsavedChangesModal as a component that needs to be launched when the user tries to leave the page when he has unsaved changes in the input fields (I have three input fields in the page).

components: {
    UnsavedChangesModal
},
mounted() {
    window.onbeforeunload = '';
},
methods: {
   alertChanges() {

   }
}
Grannie answered 25/7, 2017 at 4:18 Comment(2)
vue-router have beforeRouteLeave hookUndershoot
1. You can use vue lifecycle method - "beforeDestroy " hook as well and add a popup/dailog box before leaving page. 2 . You can use Vue-router BeforerouteLeave or use watch property on path.Maxie
L
87

Assuming you're using vue-router (and you probably should be), then you'll want to use the beforeRouteLeave guard. The documentation even gives an example of this exact situation:

beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

That can be added directly right on your component:

components: { ... },
mounted: { ... }
methods: { ... },
beforeRouteLeave (to, from, next) { ... }
Lippmann answered 26/3, 2018 at 20:25 Comment(9)
Does this works when navigating to another website / closing the browser tab as well?Marlea
@ZiadAkiki it doesn't block them for me no.Librium
upvoted! what to do if I am not using the Vue routerCoalfish
If you aren't using vue router then youll have to just bind to the window with: window.onbeforeunload = () => 'Are you sure you want to leave?'Lippmann
@Lippmann how can be it used for such a scenario? Let's say you have a route /settings/:productId then made changes for that selected product and from drop down tried to to select another product then how can dialog be implemented in this case? Since only id was changed. Because above solution didn't work.Orian
If anyone else reads this and wants a working Vue example which works even when closing the page. See this answerSyntactics
@NewTechLover you can handle using "beforeRouteUpdate" method for dynamic route paramsFluorinate
It wont work for component which are included in routing configuration.Eldrid
Anyone figure out how to better handle or suggest to user that they need to allow popups for window.confirm("message")? When I try to use this solution I see chrome blocks it. I see the following in the dev console: "Blocked confirm('Do you really want to leave? You have unsaved changes!') during beforeunload"Razo
W
22

These answers only cover navigation within Vue. If the user refreshes the page or navigates to a different site, that will not be caught. So you also need something like:

window.onbeforeunload = () => (this.unsavedChanges ? true : null);
Wentworth answered 27/4, 2020 at 10:55 Comment(2)
But how we are going to use this in vue.js. Can you please five an exampleMaclean
If anyone else reads this and wants a working Vue example see this answer.Syntactics
S
5

Are you using vue-router? I would look into navigation guards. I keep them in mind, but haven't used them myself yet. Here's the documentation on them: https://router.vuejs.org/guide/advanced/navigation-guards.html

Stir answered 25/7, 2017 at 4:25 Comment(3)
Does this guard against refreshing the page though?Mistrust
What if we dont want to use vue-router?Ephor
@Ephor You can try using life cycle hooks like: beforeDestoryRacemic
B
0

With the option API, here's how it should look inside the component that wrap the thing you want to save:

const isDirty = ref(false);

// When the user leave the page in your Vue app
onBeforeRouteLeave(() => {
    if (isDirty.value && !confirm("You have unsaved changes. Are you sure you want to leave?")) {
        return false;
    }
});

// When the user refresh/leave the current tab
useEventListener(window, "beforeunload", (event) => {
    if (isDirty.value) {
        event.preventDefault();
    }
});

The onBeforeRouteLeave will prevent the component to be unloaded due the a route leave: https://router.vuejs.org/api/#onBeforeRouteLeave

The useEventListener will automatically remove the listener when you unmount the component: https://vueuse.org/core/useEventListener/

⚠️ useEventListener requires VueUse: https://vueuse.org/

Beveridge answered 10/6 at 17:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.