29

I am a newbie on Svelte and in coding in general. I'd prefer to learn SvelteKit (Svelte@Next) rather than sapper since that seems to be where Svelte is heading.

For my personal project, I need to support dynamic routing based on url slugs. How do I do that in SvelteKit? For example, if I have /blog directory and need to pull content based on its "id", how would I do that?

The part that I am having difficulty with is accessing the URL slug parameter.

Thanks in advance.

isapir
  • 21,295
  • 13
  • 115
  • 116
Johny Chen
  • 301
  • 1
  • 3
  • 3
  • 4
    Considering SvelteKit has not been released yet (and is still changing), any answer to this question might be incorrect by the time it is actually released. – Stephane Vanraes Jan 28 '21 at 06:41
  • 1
    Today, Sapper uses 'preload' function to access its URL params. Once SvelteKit is fully up and running, it will likely render all Sapper content old and somewhat irrelevant. If how the URL parameters are accessed in SvelteKit changes in its early days, the answer here could very easily be updated. – Johny Chen Jan 28 '21 at 07:42

4 Answers4

38

As of SvelteKit 1.0 the path should be a directory in brackets, e.g. for /blog/<slug> you will add the following:

src/routes/blog/[slug]
  |_ +page.js
  |_ +page.svelte

Then in src/routes/blog/[slug]/+page.js you can add something like

export const load = ({ params }) => {
    return {
        slug: params.slug
    }
}

which will return it as a data property to +page.svelte, so you can write something like:

<script>
    export let data;
</script>

<h1>{data.slug}</h1>

Reference: https://kit.svelte.dev/docs/routing

isapir
  • 21,295
  • 13
  • 115
  • 116
27

WARNING: THIS SOLUTION IS NOW DEPRECATED

  • you can create a file with the [brackets] : touch src/routes/blog/[slug].svelte

Vscode tree

And paste the following code

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

{$page.params.slug}

Then navigate to your app http://localhost:3000/blog/123

You should see your result

result svelte kit slug

In order to create content for the http://localhost:3000/blog page, you can modify src/routes/blog/index.svelte

cassepipe
  • 371
  • 6
  • 16
KillianGDK
  • 1,922
  • 1
  • 8
  • 9
  • how do i get route name? – chovy Dec 08 '21 at 02:58
  • What do you mean ? Your route name is defined by your folder architecture. If your folder is named "my-route" in your src folder, then your url will be "{base_url}/my-route". – KillianGDK Dec 10 '21 at 09:16
  • Thanks for the answer, I'm curious what does $ mean here? [ in $page variable ] – a3k Dec 28 '21 at 14:09
  • 1
    From my understanding, in SvelteKit, page is generated as a store element. And in svelte, if you want to access store elements you need to prefix them with $. page documentation : https://kit.svelte.dev/docs#loading-input-page – KillianGDK Dec 30 '21 at 09:10
  • 15
    this is deprecated now. please update. – chovy Feb 08 '22 at 19:21
  • 3
    check @isapir 's answer below for updated. – sutan Jan 13 '23 at 15:59
4

Caveat - the info in my reply probably may not be valid as SvelteKit matures, but from experiments I have done thus far, this works:

Parameter based routing is similar to the sveltejs/sapper-template. You should learn how Sapper does it first. Lets say I have a route blog with a single param slug (/blog/page-1 & /blog/page-2)

  1. Create a route component in routes/blog named [slug].svelte
  2. Copy the content from the sveltejs/sapper-template example.
  3. Rename the preload function to load with a single parameter such as ctx
  4. Alter the return object to append your slug property to props
export async function load(ctx) {
  let slug = ctx.page.params.slug
  return { props: { slug }}
}

If your blog has multiple params for the slug (/blog/2021/01/29/this-is-a-slug), you can remove [slug].svelte and create a file name [...data].svelte and change your load method to:

export async function load(ctx) {
  let [year, month, day, slug] = ctx.page.params.data;
  return { props: { data: { year, month, day, slug }}}
}

Don't forget to define your data property as an object. Here's a typescript example:

<script lang="ts">
    export let data: { slug:  string, year: number, month: number, day: number };
</script>

From there use the values as {data.slug}, etc

Happy hacking

  • When I try to get the different parameters from [...data], I am unable. All I can get is just one string with the rest of the parameters. I am working with Sveltekit. – jap1968 Sep 18 '21 at 09:26
  • Thanks for mentioning the `[...data]`. This way I was able to create a `[...path]` directory and match all URLs. When a page is loaded, `params.path` is for example `''` for homepage, or `'use-cases/something'` for a nested page. – Jan Švábík Apr 15 '23 at 12:11
3

I also had some issues with the Typescript import so here is a complete Typescript example.

Structure:

src/routes/coins/[coin_name]
  |_ +page.ts
  |_ +page.svelte

+page.ts:

import type { PageLoad } from './$types';

export const load: PageLoad = ({ params }) => {
    return {
        name: params.coin_name
    }
}

export interface CoinPage{
    name: string
}

+page.svelte and the use of the data:

<script lang="ts">
    import type { CoinPage } from "./+page";

    export let data:CoinPage;
</script>

<h1>{data.name}</h1>
Csicsi
  • 31
  • 1