mefechoel / svelte-navigator

Simple, accessible routing for Svelte

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Prompt for unsaved forms

iluuu1994 opened this issue · comments

Thank you for this library!

I'm looking for something like React routers Prompt.

When there is unsaved work there are three ways the user should be warned:

  1. window.onbeforeunload: The user presses refresh in the browser or navigates to another website
  2. navigate: The user presses on an internal link that will change the page in the router
  3. popstate: The user presses back in the browser

1 and 2 are solvable relatively easily. createHistory could allow registering callbacks for handling prompts. If any of these listeners return an unsuccessful value (as in there is unsaved work) a prompt would be displayed.

3 is a bit more tricky since the browser doesn't offer a way to block the URL change. Thus on cancel we'd have to navigate back to the page the user just left. This would have to be done before the router removes anything from the page so that no state is lost. This is what react-router does, I think.

Has any work in this area been done? I'll create an implementation if you don't see anything wrong with this approach.

  1. Can be solved by adding the following code to the <script/> of your router object.
history.pushState = new Proxy(history.pushState, {
        apply (target, thisArg, argumentsList) {
            // Code here will execute *before* the navigation (and may prevent it by return-ing early)
            // ... code ...
            Reflect.apply(target, thisArg, argumentsList);
            // Code here will execute *after* the navigation
            // ... code ...
        }
    })

I still would appreciate official support for this!

I'm hesitant to add this to the library (for now) as it would require quite a bit of modification to the history module, as well as some new components (a Prompt component probably).

Yout described solution using a proxy will work, but only on pushstate calls, which is only half the story. Browser back and forth buttons won't be intercepted here.
That's why I'd recommend using a history module that already supports blocking. Take a look at the browser history from the npm history module. You can the use that history with svelte navigator (see custom history section of readme and custom hash history example).

I'm hesitant to add this to the library (for now) as it would require quite a bit of modification to the history module, as well as some new components (a Prompt component probably).

Yout described solution using a proxy will work, but only on pushstate calls, which is only half the story. Browser back and forth buttons won't be intercepted here. That's why I'd recommend using a history module that already supports blocking. Take a look at the browser history from the npm history module. You can the use that history with svelte navigator (see custom history section of readme and custom hash history example).

i think it will be very helpful in this case if you can provide any way to replace the global history, including the default navigate exported by the library