Multiple slots/snippets in the layout in svelte 5 #14108
Replies: 6 comments 13 replies
-
This works but it doesn't SSR. I have a working solution to SSR them but it's a bit brittle and I need to explore possible edge case better. |
Beta Was this translation helpful? Give feedback.
-
I have an example using an SSR compatible approach over here (SvelteLab). (CC. @paoloricciuti) |
Beta Was this translation helpful? Give feedback.
-
I created a couple of solutions that use the page store with runes instead of using getContext / setContext. The main Otherwise, the first example is based on @brunnerh's great idea to use Use the shared page store + layout render children The second example uses an external component to load snippets and attach to the page store via the same mechanism as above. In this case there is no need to use the |
Beta Was this translation helpful? Give feedback.
-
And this option? store.ts: import type { Snippet } from 'svelte';
let Header: Snippet;
export let setHeader = (snippet: Snippet) => (Header = snippet);
export let getHeader = (): Snippet => Header;
let Footer: Snippet;
export let setFooter = (snippet: Snippet) => (Footer = snippet);
export let getFooter = (): Snippet => Footer; +layout.svelte: <script lang="ts">
import { getHeader, getFooter } from '$lib/scripts/store';
import { type Snippet } from 'svelte';
let { children } = $props();
let header: Snippet = $state() as Snippet;
let footer: Snippet = $state() as Snippet;
$effect(() => {
header = getHeader();
footer = getFooter();
});
</script>
{@render header?.()}
{@render children?.()}
{@render footer?.()} +page.svelte <script lang="ts">
import { setHeader, setFooter } from '$lib/scripts/store';
setHeader(header);
setFooter(footer);
</script>
{#snippet header()}
Header
{/snippet}
<div>Content</div>
{#snippet footer()}
Footer
{/snippet} |
Beta Was this translation helpful? Give feedback.
-
I was hoping to be able to simply: +layout.svelte <script lang="ts"
import type { Snippet } from 'svelte'
interface Props {
children?: Snippet
header?: Snippet
footer?: Snippet
}
let {children, header, footer }: Props = $props()
</script>
{@render header?.()}
{@render children?.()}
{@render footer?.()} |
Beta Was this translation helpful? Give feedback.
-
Instead of relying on the layout, you can use an additional component and composition instead of "inheritance". <script lang="ts">
interface Props {
header: import('svelte').Snippet;
content: import('svelte').Snippet;
}
let { header, content }: Props = $props();
</script>
<div class="text-xl h-full flex flex-col">
<div class="p-2 bg-blue-800">
{@render header?.()}
</div>
<div class="bg-white flex-grow">
{@render content?.()}
</div>
</div> Then you get full type-safety and the 'input snippets' of your layout are type-checked when authoring your pages: <UiLayout>
{#snippet header()} <!-- if this was missing, it would be an error -->
My Header
{/snippet}
{#snippet content()}
My Content
{/snippet}
</UiLayout> |
Beta Was this translation helpful? Give feedback.
-
Describe the problem
In svelte 4, it was not possible to use multiple slots in the layout.
Snippets have appeared in svelte 5, which should replace slots, and for myself I found such an option for several snippets in the layout. It works fine, maybe it will be useful to someone.
I wanted to ask, how valid is this?
My store file (store.ts):
My +layout.svelte:
My +page.svelte
Describe the proposed solution
I wanted to ask, how valid is this?
Importance
would make my life easier
Beta Was this translation helpful? Give feedback.
All reactions