Johny Chen
Johny Chen

Reputation: 391

SvelteKit: how do I do slug-based dynamic routing?

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.

Upvotes: 38

Views: 54289

Answers (5)

Jason Goemaat
Jason Goemaat

Reputation: 29214

I upvoted @isapir's answer because it helped, but here's how I did it with the most recent Svelte with a little change...

I have /routes/characters/[slug]/+page.ts, I always seem to forget the leading '+' which causes an error with params, but here's working code:

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

Then in /routes/characters/[slug]/+page.svelte:

<script lang="ts">
    let { data } = $props();
</script>

<h1>Character id: {data.slug}</h1>

Upvotes: 2

KillianGDK
KillianGDK

Reputation: 2648

You can create a file at src/routes/blog/[slug]/+page.svelte

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/+page.svelte

Upvotes: 31

Csicsi
Csicsi

Reputation: 31

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>

Upvotes: 3

isapir
isapir

Reputation: 23483

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

Upvotes: 52

user2526098
user2526098

Reputation: 51

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

Upvotes: 4

Related Questions