admin管理员组

文章数量:1123781

New to SvelteKit and trying to figure this part out...

Here's a couple of ways I was trying to achieve this, but the sidebar either doesn't load, or the navigation appears twice for some reason; with the snippet text only appearing in the second instance. I started searching Github to review examples via path:**/+layout.svelte /@render children/ and path:**/+layout.svelte /children: Snippet; *: Snippet, but there are no results that actually import and use duplicate renders; from what I've seen. I planned to use +layout.svelte to breakdown my site into Header, Sidebar, Main and Footer and dynamically change the content based on +page.svelte. The docs touch on this and I've seen it done with cards and +page.svelte, but not in +layout.svelte itself. Am I doing this wrong?

+layout.svelte

<script lang="ts">
    import "../app.css";
    import type { Snippet } from "svelte";
    import { sineIn } from "svelte/easing";
    import { Drawer, Sidebar } from "flowbite-svelte";

    // Destructure specific props from $props()
    interface Props {
        children?: Snippet;
        filterSidebar?: Snippet<[() => void]>;
    }
    let { 
        children, 
        filterSidebar
    }: Props = $props();

    const transitionParams = {
        x: -320,
        duration: 200,
        easing: sineIn
    };

    let hidden = $state(true);

    function toggleSidebar(): void {
        hidden = !hidden;
    }
</script>
<div class="header flex items-center justify-between p-5 border-b">
    <h1 class="text-xl">SvelteKit Render Test</h1>
    <button
        aria-label="Toggle Filters"
        onclick={toggleSidebar}
    >
        <svg
            class="w-6 h-6"
            xmlns=";
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
        >
            <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M4 6h16M4 12h16m-7 6h7"
            />
        </svg>
    </button>
</div>
<Drawer transitionType="fly" {transitionParams} bind:hidden={hidden} id="sidebar">
    <Sidebar asideClass="w-full">
        {@render filterSidebar?.(toggleSidebar)}
    </Sidebar>
</Drawer>
<main>
    {@render children?.()}
</main>


+page.svelte v1

<script lang="ts">
    import Layout from "./+layout.svelte";
    import { CloseButton, SidebarGroup } from "flowbite-svelte";=
</script>
{#snippet filterSidebar(toggleSidebar: () => void)}
    <SidebarGroup ulClass="flex items-center">
        <h1>Filters</h1>
        <CloseButton onclick={toggleSidebar} />
    </SidebarGroup>
{/snippet}
<h1>Test Element</h1>

Results +page.svelte v1


+page.svelte v2

<script lang="ts">
    import Layout from "./+layout.svelte";
    import { CloseButton, SidebarGroup } from "flowbite-svelte";
    console.log("Page rendered");
</script>
<Layout>
    {#snippet filterSidebar(toggleSidebar: () => void)}
        <SidebarGroup ulClass="flex items-center">
            <h1>Filters</h1>
            <CloseButton onclick={toggleSidebar} />
        </SidebarGroup>
    {/snippet}
    <h1>Test Element</h1>
</Layout>

Results +page.svelte v2

New to SvelteKit and trying to figure this part out...

Here's a couple of ways I was trying to achieve this, but the sidebar either doesn't load, or the navigation appears twice for some reason; with the snippet text only appearing in the second instance. I started searching Github to review examples via path:**/+layout.svelte /@render children/ and path:**/+layout.svelte /children: Snippet; *: Snippet, but there are no results that actually import and use duplicate renders; from what I've seen. I planned to use +layout.svelte to breakdown my site into Header, Sidebar, Main and Footer and dynamically change the content based on +page.svelte. The docs touch on this and I've seen it done with cards and +page.svelte, but not in +layout.svelte itself. Am I doing this wrong?

+layout.svelte

<script lang="ts">
    import "../app.css";
    import type { Snippet } from "svelte";
    import { sineIn } from "svelte/easing";
    import { Drawer, Sidebar } from "flowbite-svelte";

    // Destructure specific props from $props()
    interface Props {
        children?: Snippet;
        filterSidebar?: Snippet<[() => void]>;
    }
    let { 
        children, 
        filterSidebar
    }: Props = $props();

    const transitionParams = {
        x: -320,
        duration: 200,
        easing: sineIn
    };

    let hidden = $state(true);

    function toggleSidebar(): void {
        hidden = !hidden;
    }
</script>
<div class="header flex items-center justify-between p-5 border-b">
    <h1 class="text-xl">SvelteKit Render Test</h1>
    <button
        aria-label="Toggle Filters"
        onclick={toggleSidebar}
    >
        <svg
            class="w-6 h-6"
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
        >
            <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M4 6h16M4 12h16m-7 6h7"
            />
        </svg>
    </button>
</div>
<Drawer transitionType="fly" {transitionParams} bind:hidden={hidden} id="sidebar">
    <Sidebar asideClass="w-full">
        {@render filterSidebar?.(toggleSidebar)}
    </Sidebar>
</Drawer>
<main>
    {@render children?.()}
</main>


+page.svelte v1

<script lang="ts">
    import Layout from "./+layout.svelte";
    import { CloseButton, SidebarGroup } from "flowbite-svelte";=
</script>
{#snippet filterSidebar(toggleSidebar: () => void)}
    <SidebarGroup ulClass="flex items-center">
        <h1>Filters</h1>
        <CloseButton onclick={toggleSidebar} />
    </SidebarGroup>
{/snippet}
<h1>Test Element</h1>

Results +page.svelte v1


+page.svelte v2

<script lang="ts">
    import Layout from "./+layout.svelte";
    import { CloseButton, SidebarGroup } from "flowbite-svelte";
    console.log("Page rendered");
</script>
<Layout>
    {#snippet filterSidebar(toggleSidebar: () => void)}
        <SidebarGroup ulClass="flex items-center">
            <h1>Filters</h1>
            <CloseButton onclick={toggleSidebar} />
        </SidebarGroup>
    {/snippet}
    <h1>Test Element</h1>
</Layout>

Results +page.svelte v2

Share Improve this question asked yesterday Brad TBrad T 234 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

As far as I know, SvelteKit doesn't provide any way for a +page.svelte file to pass information to a +layout.svelte file. You can use a global store that the +page.svelte file writes values to and the +layout.svelte file reads values from, or similar, but not a very clean solution IMO.

Another workaround is that you don't use +layout.svelte files at all, and instead create your layout as an ordinary Svelte component (e.g. $lib/Layout.svelte), and then in each of your +page.svelte files uses that <Layout> component. This way, you can pass any snippets you want to your <Layout> component, but the downside is that you aren't taking advantage of the layout system available in SvelteKit, so performance might hurt a little, but I don't think that will be noticeable (I'm guessing the <Layout> component will be deleted and recreated on each navigation).

本文标签: