I hope to insert multiple different components into the specified {@render} of the upper layout at different routing sub-levels. Since I don’t know a simple way to pass these components to the default children props, my requirement is actually As the title of this question suggests, named slots are used in layouts. I currently use the following code to solve the needs, but I intuitively think that my way is bad and very circuitous, and I do not need to dynamically change the inserted components after loading the page, but I use additional code in order to pass these snippets The writable store and Context methods are added.
Hopefully someone can give me a better idea for my current approach, maybe there should be a direct way to pass props in the +page.svelte html area, but I can't find it.
//+layout.svelte
<script lang="ts">
import { setContext, createRawSnippet } from 'svelte';
import { writable } from 'svelte/store';
const dummySnippet = (text: string) =>
createRawSnippet(() => {
return { render: () => text };
});
let { children } = $props();
let slotLeft = writable(dummySnippet('LEFT'));
let slotCenter = writable(dummySnippet('CENTER'));
let slotRight = writable(dummySnippet('RIGHT'));
setContext('LayoutSlot', { slotLeft, slotCenter, slotRight });
</script>
<winbox class="flex flex-row h-full w-full overflow-hidden">
<listbox class="w-[400px]">
{@render $slotLeft()}
</listbox>
<div class="flex-1 flex flex-col border-x">
{@render $slotCenter()}
</div>
<div class="w-[350px]">
{@render $slotRight()}
</div>
</winbox>
{@render children()}
// +page.svelte
<script lang="ts">
import { onMount, getContext, type Snippet } from 'svelte';
import type { Writable } from 'svelte/store';
let {
slotLeft,
slotCenter,
slotRight
}: {
slotLeft: Writable<Snippet>;
slotCenter: Writable<Snippet>;
slotRight: Writable<Snippet>;
} = getContext('LayoutSlot');
onMount(() => {
$slotLeft = menuLeft;
$slotCenter = mainContent;
$slotRight = menuRight;
});
</script>
{#snippet menuLeft()}
<p>Left Menu Pending</p>
{/snippet}
{#snippet mainContent()}
<p>Center Content Pending</p>
{/snippet}
{#snippet menuRight()}
<p>Right Menu Pending</p>
{/snippet}
<children>TEST</children>
<!-- .... other option snippets from other routing-->
<!-- {#snippet foo1()} -->
<!-- {#snippet foo2()} -->
In addition, when I use this method, I will receive a warning on the browser
[svelte] invalid_raw_snippet_renderThe
render
function passed tocreateRawSnippet
should return HTML for a single element
Top comments (5)
You should check out svelte’s reddit (or ask there) — I saw some similar discussions there, the community is pretty active in terms of v5 migration implications
I have searched for similar topics, but they have nothing to do with layout. Unfortunately, I only found out after asking questions on reddit that I forgot to disconnect the proxy, which resulted in my reddit account being banned. . . I'm still trying to find a solution, thank you for your suggestions.
It’s true that I haven’t gotten used to the changes in version 5, but I like these new features, it just takes some time to adapt.
Just take the new svelte tutorial, it says that snippets inside a component are passed as a prop. svelte.dev/tutorial/svelte/implici...
I found that I had seen this tutorial. According to my superficial knowledge, this method is only suitable for passing variables to component, but I can't find a way other than "context" to simplify my code.
The problem is that the general method of passing props from the +page.svelte file to +layout is in the html area. I hope that like version 4, I can use {@snippet render="xxx"} or in the html of +page. I specify the location of render.
Anyway, I will keep trying, thanks very much
Okay, I'll go take a look right away, thank you for your help