Svelte goto using slug

584 Views Asked by At

I'm using svelte for a personnal project and i'm wondering if someone has the trick to do that.

I've a list of blog pages and for each pages i've a next_page and previous_page url The problem is:

from the url /blog/[blogname]

with next_page = "/blog/[nextblogname]" previous_page = "/blog/[previousblogname]"

the href or goto function change the url to the right one but never trigger the +page.js execution that load the right blog content with the api call

I guess i missed something in the dynamic routing setup ?

Thanks in advance !

i tried:

+page.svelte

<a href="/blog/2">
    next page
</a>

+page.server.js / +page.js

<script>
    import { goto } from '$app/navigation';
    function next_page() {
        goto("/blog/2");
        // also tested goto("/blog/2", {replaceState: true});
    }
</script>
<div on:click={() => next_page()}>
    next page
</div>

I also tried to load everything from the .svelte file but it's also not working

I tried to create a component on which you give the blog infos but the .svelte dont refresh

Progress: I changed the +page.js into +page.server.js and new blog infos are loaded server side, but client side the page don't refresh and don't display/catch the new blog informations

I also tried:

+page.js

import component from "./blog_content.svelte";
export function load({ fetch, params}){

    // load my blog content

    return {
        blog_data: data,
        component
    };
)

+page.svelte

{#if $page.data.component}
    <svelte:component this={$page.data.component} blog_data={blog_data}/>
{/if}

But it changes nothing

if i try to change the page.js into page.server.js it says

Error: Data returned from 'load' while rendering /blog/[blogId] is not serializable: Cannot stringify a function

2

There are 2 best solutions below

0
brunnerh On BEST ANSWER

Just as the error states: You cannot serialize a function (in this case a component).

If you want to dynamically change what component is being displayed, you have to approach that differently, e.g. only send a component name and resolve that on the page.

In most cases that should not be necessary at all, in your example you always send the same component anyway. Just import that on the page and use it directly.

<BlogContent {blog_data} />
0
Samuel Pelsy On

For people joining and having the same issue i wanted to rewrite a comment on how i did it :

routes/api/blog/+server.js

export async function GET({ url }) {
    // search params on url
    my_param = url.searchParams.get('XXX');
 
    ...

    // process everything you need 
    // return_data : {status: int, blog: any}
    return_data = ...

    ...

    return json(return_data)
}

routes/blog/[blogId]/+page.js

/** @type {import('./$types').PageLoad} */
export async function load({ fetch, params }) {
    const blog_id = params?.blogId;
    let blog = {};
    if(blog_id)
    {
        const response = await fetch(`/api/blog?blogId=` + params.blogId)
        blog = response.json()

    }
    return {
        status: 200,
        blog: blog
    }
}

routes/blog/[blogId]/+page.svelte

<script>
    import BlogDetail from './blog_detail.svelte';

    export let data;
    $: content = data
</script>

{#await data}
    ...  // spinner or something that wait
{:then content}
    <BlogDetail blog_content={content?.blog}/>
{:catch}
    An error occured...
{/await}

routes/blog/[blogId]/blog_detail.svelte

<script>
    export let blog_content;
</script>

{#if blog_content === undefined}
    ... // write something about you didn't found anything
{:else}
    ... // use blog_content.xxx
{/if}

I hope it will helps people in trouble having the same issue ! Feel free to post/comment if you have questions