Skip to content

GET form triggers an entire page reload if rendered outside of SvelteKit's root #7940

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
arackaf opened this issue Dec 4, 2022 · 10 comments · Fixed by #7969
Closed

GET form triggers an entire page reload if rendered outside of SvelteKit's root #7940

arackaf opened this issue Dec 4, 2022 · 10 comments · Fixed by #7969
Labels
documentation Improvements or additions to documentation
Milestone

Comments

@arackaf
Copy link

arackaf commented Dec 4, 2022

Describe the bug

If a form is rendered outside of SvelteKit's content, and triggers a navigation, the entire page reloads.

This might seem like an absurd thing to care about, but a search form inside of a modal, rendered in a portal is a reasonably common occurrence, and exactly how I discovered this.

Incidentally, form actions appear to work fine. You can post from a form rendered in a portal, and the invalidation appears to work correctly, without the full reload

Reproduction

https://github.com/arackaf/svelte-kit-form-nav-repro

First textbox is rendered inside of SvelteKit, and works correctly.

Second one is rendered in a portal, and triggers a full page reload.

Logs

n/a

System Info

System:
    OS: macOS 13.0.1
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 208.96 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 16.11.1 - /usr/local/Cellar/nvm/0.38.0/versions/node/v16.11.1/bin/node
    Yarn: 1.22.17 - /usr/local/Cellar/nvm/0.38.0/versions/node/v16.11.1/bin/yarn
    npm: 8.18.0 - ~/Documents/node_modules/.bin/npm
  Browsers:
    Chrome: 108.0.5359.94
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.90
    @sveltejs/kit: next => 1.0.0-next.571
    svelte: ^3.53.1 => 3.53.1
    vite: ^3.2.4 => 3.2.4

Severity

serious, but I can work around it

Additional Information

No response

@Conduitry
Copy link
Member

Probably this is working as intended, and should just be documented. We just want to attach event handlers to the SvelteKit root. There was a comment somewhere recently that I can't find about someone realizing they needed to render a modal/popup within the SvelteKit root instead of directly in document.body.

@Conduitry Conduitry added the documentation Improvements or additions to documentation label Dec 4, 2022
@Rich-Harris
Copy link
Member

It's a fairly recent change (and not specific to forms — same applies to links): #7763. The second comment on that issue (which I didn't see because the issue was closed) is basically the same as this but in a different form (pun not intended).

I think it's generally preferable to do stuff inside the SvelteKit root, but the comment in that other issue mentions Popper. In cases where user components are being moved outside the SvelteKit root by library code, there's not a whole lot we can do.

Honestly not sure how to solve this without reverting #7763, which we don't want to do.

@arackaf
Copy link
Author

arackaf commented Dec 4, 2022

In cases where user components are being moved outside the SvelteKit root by library code

Right, that's exactly what this issue is. Nobody would ever manually render a Svelte form outside of SvelteKit's root. But most modal libraries will do exactly that (or popovers, tooltips, etc).

I'd personally much prefer to see SvelteKit prioritize first-class application development over the ability to embed into some other app (ie by seamlessly supporting things like Popovers, tooltips, modals) but that's of course beyond my paygrade.

@arackaf
Copy link
Author

arackaf commented Dec 4, 2022

I know configuration flags are a wonderful way to increase complexity, and probably the bane of most maintainers' existence, but could this be configurable?

Wanting to embed a SvelteKit app into another app doesn't seem like a common, or default use case. Could this root-only event handling be opted into with some sort of embeddable flag?

@Rich-Harris Rich-Harris added this to the 1.0 milestone Dec 5, 2022
@Rich-Harris
Copy link
Member

Configuration might be the least worst option, I don't know. Marking this as 1.0 milestone because if we were to revert to listening on window unless there were some embedded: true option (or whatever) it would be a breaking change, so we ideally need to figure it out before then

@PatrickG
Copy link
Member

PatrickG commented Dec 5, 2022

How about a data-sveltekit-root attribute, and using document.body (or document.documentElement?) if no element with this attribute is found?

@dummdidumm
Copy link
Member

Whether we use a config option or data-sveltekit-root - could that also be used to solve #4935 (comment), allowing for #4935 to be merged with the modification that it checks for the config option/attribute before deciding which way to go (using the url or what's passed from the server)?

@Rich-Harris
Copy link
Member

data-sveltekit-root wouldn't work in the case where you have multiple SvelteKit embeds on a single page, I think (which has sometimes been the case on the NYT homepage). You'd only ever want it to be the container of %sveltekit.body% anyway, no? In which case a boolean config option probably makes more sense.

Then again the existence of a module in the SvelteKit codebase called singletons.js is a clue that we haven't quite nailed the embed case anyway — if you have two instances, it only works if the router is disabled in one or both, since both router instances will respond to the same popstate events.

@arackaf
Copy link
Author

arackaf commented Dec 5, 2022

Sorry to drag this a bit down into the weeds amidst this great discussion, but can I ask if the behavior I described above, of (progressively enhanced) form actions working safely, even if the form (and submit button) are outside of the SvelteKit root, is reliable, in the absence of whatever solution you all land on? Ie, is this supposed to work, or does this just happen to work, and might stop working with some possible, non-breaking change in the future.

@PatrickG
Copy link
Member

PatrickG commented Dec 5, 2022

data-sveltekit-root wouldn't work in the case where you have multiple SvelteKit embeds on a single page, I think (which has sometimes been the case on the NYT homepage). You'd only ever want it to be the container of %sveltekit.body% anyway, no? In which case a boolean config option probably makes more sense.

What I had in my mind was, that you could have multiple data-sveltekit-root elements – one for each %sveltekit.body% – which would be used as the target attribute for the start function here.
I don't know if that makes sense 😅

dummdidumm added a commit that referenced this issue Dec 6, 2022
Closes #7940
Adds a new option which defaults to false. If true, events related to navigation etc are listened to on the target element rather the html root
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants