Prompt on back button navigation
react-router has Prompt widget to handle back button navigation from pages where the user has un-saved data.
There was a related issue in the past where the use of onbeforeunload was suggested as a solution. I've tried that and could not get it to work.
React-router works differently and I think that approach could be applied here. Basically it lets the navigation happen but the routing wrapper keeps the previous route active and brings up a prompt dialog to ask if the user really wants to navigate away.
If the answer is no, it pushes the route back on the history and no data is lost. If the answer is yes, then the back route becomes active.
Would it be possible to do the same here? A non DOM-element component that would only manipulate variables in the top router context/store could do the job, I think.
onbeforeunload will only work for cases when the user navigates away without the router (reload, link to a different website, link that isn't a <Link /> or use:link). Unfortunately svelte-routing doesn't provide a way to listen to location changes.
One way to achieve this would be by passing the location store as a slot property here:
<slot {location}></slot>
Alternatively the context keys could be exported so that they are accessible from outside the svelte-routing library.
I'm guessing this wasn't done to not expose too many implementation details, or to avoid mutation of internal state? If so, is there a preferable solution? I'd like to create a PR if you provide some more details.
It's not quite as easy as I thought because not only do you need to listen to changes of the url but you need to intercept some other events, like popstate and beforeunload. It's currently not possible in this library because much of the internals are hidden.
It's not possible in svelte-navigator (a fork of this router) either but more of the internals is exposed which allowed this to be implemented more easily. I created a PR here but whether this will get merged is unclear at this point.
Svelte Routing v1.8 has been released, which added useLocation hook, by using it you can track if location or route changes.
Svelte Routing v1.8 has been released, which added
useLocationhook, by using it you can track if location or route changes.
Is this documented?
Svelte Routing v1.8 has been released, which added
useLocationhook, by using it you can track if location or route changes.Is this documented?
Yes in the changelog
@krishnaTORQUE i tried to get it setup on my Project but i am not able to prevent the Back and Forth Button. If you already implemented it using the new hooks i would really appreciate if you share a basic example of how you implemented it!
Basic example
<script lang="ts">
import { useLocation } from "svelte-routing";
const location = useLocation();
let previousLocation: string = $location.pathname;
$: {
if (previousLocation !== $location.pathname) {
console.log("Location changed");
console.log("Previous Url:", previousLocation);
console.log("Current Url:", $location.pathname);
previousLocation = $location.pathname;
}
}
</script>
Thank you! This only triggers after a Route was changed, not before. Tried to implement this in a Page Component and also inside the main App Component, should the $location change before the Route changes?
@krishnaTORQUE do you have any idea on how to get this working? I would really appreciate!
@julianlaibach Maybe I am wrong but I dont think that we can do something like this. Basically when route change we call a function. If it does not change there is no event, so no way we can detect the route is about to change. I updated my last code example.
@krishnaTORQUE thank you for your quick reply. The Route updates but your Code example triggers after the Route changed, so i have no chance to prevent the Navigation before Route change. Someting like the Pop State Event would be awesome! https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event
Please let me know if you think there would be a way!
@julianlaibach I dont think you get my point. If the route does not change then how would I know that it is about to change in next 1 second or in 1 hour. Once it is change we call a function for re-render. You can do something like this below,
<script lang="ts">
import { useLocation } from "svelte-routing";
const location = useLocation();
let previousLocation: string = $location.pathname;
$: {
if (previousLocation !== $location.pathname) {
console.log("Location changed");
console.log("Previous Url:", previousLocation);
console.log("Current Url:", $location.pathname);
if(doNotNavigate()) window.location.href = previousLocation;
else previousLocation = $location.pathname;
}
}
</script>
doNotNavigate function is your custom function to check should navigation or not. If not then go back.
Hope this helps
@krishnaTORQUE thank you in advance, no i got your point and got it to work!
@julianlaibach Great. Happy to help.