Skip to content

Support for global query params that get preserved on navigation #734

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
wighawag opened this issue Mar 28, 2021 · 11 comments
Closed

Support for global query params that get preserved on navigation #734

wighawag opened this issue Mar 28, 2021 · 11 comments
Labels

Comments

@wighawag
Copy link
Contributor

Is your feature request related to a problem? Please describe.
Currently I need to keep track of query string that are supposed to be used across the application and inject them in every link.
This is because svelte will take in consideration the given href and if that href do not contains any query string, then none will appear in the next navigation.

This is expected as this is the normal behaviour for browser. But it is often the case that query string are used as global config across the app and for it to not get reset on every navigation, we need to ensure it get added there every time. This is especially important in the context of static site.

This would be great if there was a way to inject these on navigation in svelte kit (maybe it is already possible somehow?)

An example of a router that support that quite easily is curi

Describe the solution you'd like
The solution that might make more sense is to let user of svelte kit transform navigation request. Like there could be a onNavigation callback where we can change the request.

How important is this feature to you?
Without it I would need to remove the use of <a href links and use a component that inject the global query params.

@antony
Copy link
Member

antony commented Mar 28, 2021

Query string parameters should pertain to the page they are appended to - if you want to change global state based on them, then you can do as I do, and set a store value as soon as the query parameter has been set. You can do this by subscribing to the page store in your layout.

Do you have a concrete use-case for passing the same query parameters to each page, which stops you using a global store or browser local storage?

@wighawag
Copy link
Contributor Author

wighawag commented Mar 28, 2021

Storing the value in a store is not enough for my use case as I want it to be reflected in the url.
Similarly storing in local storage (and not in the url) make the url non-portable anymore. It also does not work where local storage / cookies are not enabled.

The use cases are multiple. Here is an example : https://jolly-roger.eth.link/demo/?subgraph=https://api.thegraph.com/subgraphs/name/wighawag/purple-warlock-staging

this is now a shareable url that you can use, navigate, then bookmark and share yourself. It will always use the same graphql endpoint.

Basically once the query params are supposed to affect the app in a global manner, it is important to have it reflected in the url after navigation, so it is not being dependent on the context (which user, whether they have local storage, etc....)

@benmccann
Copy link
Member

The solution that might make more sense is to let user of svelte kit transform navigation request. Like there could be a onNavigation callback where we can change the request.

I wonder if we should close this as a duplicate of #560 which requests an onNavigate?

@dummdidumm
Copy link
Member

I don't think it's exactly the same use case, at least if onNavigate is not able to change the route

@Rich-Harris
Copy link
Member

This can be achieved like so:

<script>
  import { page } from '$app/stores';
</script>

<a href="/whatever{$page.url.search}">whatever</a>

I think this is a sufficiently niche requirement that SvelteKit doesn't need to make it any more convenient than that.

@wighawag
Copy link
Contributor Author

wighawag commented Apr 7, 2022

to clarify @Rich-Harris your solution does not fulfil the requirement stated in the original post because

  • it requires to add that to all href and you need to handle cases where you want to add more parameter (non-global)
  • it will preserve all query param, (and while some query param have global scope, some do not)

I understand that this might not be wanted in the core of svelte/kit but a mechanism to support such feature (where you can continue using href like normal) would be great.

@benmccann mentioned the use of onNavigate and I see that #3293 has been merged. I ll have a go and see if that can fulfil my need

Thanks

@einarpersson
Copy link

@wighawag Did you get this to work? I have the same situation and I do not want to modify every single <a href on my site.

@wighawag
Copy link
Contributor Author

wighawag commented Sep 8, 2022

@einarpersson I use my own url function that transform url like so

<script>
  import { url } from '$lib/utils/url;
</script>

<a href={url('/about')}>About</a>
<a href={url('/page?supportNonGlobalParams=test')}>My page</a>

See : https://github.com/wighawag/jolly-roger/blob/main/web/src/lib/utils/url.ts
the set of global query param is configurable

It would be better if svelte kit allowed us to customize url behavior. Unfortunately The onBeforeNavigate hook linked here does not let us modify the navigation url

@einarpersson
Copy link

@wighawag

alright, I ended up using beforeNavigate in +layout.svelte like this:

beforeNavigate(({ from, to, cancel }) => {
    if (from.url.searchParams.has('foo') && !to.url.searchParams.has('foo')) {
      cancel()
      goto(to.url.pathname + `?foo=${from.url.searchParams.get('foo')}`)
    }
  })

@wighawag
Copy link
Contributor Author

wighawag commented Sep 8, 2022

Intesresting, was thinking to try something along these lines,

does it have undersired side effect or is it completely fine to use beforeNavigate like that ?

and is svelte-kit going to support that use long term ?

@benmccann what do you think ?

@PatrickG
Copy link
Member

PatrickG commented Sep 8, 2022

@wighawag

alright, I ended up using beforeNavigate in +layout.svelte like this:

beforeNavigate(({ from, to, cancel }) => {
    if (from.url.searchParams.has('foo') && !to.url.searchParams.has('foo')) {
      cancel()
      goto(to.url.pathname + `?foo=${from.url.searchParams.get('foo')}`)
    }
  })

Keep in mind that this does not work without javascript.
And to can be null, I guess your if statement throws an error if you click on an external link.
Also, you are removing all other query params (might be ok in your case).

and is svelte-kit going to support that use long term ?

I don't see reason why sveltekit would stop supporting this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants