DEV Community

Thomas Choi
Thomas Choi

Posted on

Does svelte5 have multi {@render} equivalent to ver.4’s multi named slot use inside +layout.svelte?

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()}
Enter fullscreen mode Exit fullscreen mode
// +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()} -->
Enter fullscreen mode Exit fullscreen mode

In addition, when I use this method, I will receive a warning on the browser

[svelte] invalid_raw_snippet_renderThe render function passed to createRawSnippet should return HTML for a single element

Top comments (1)

Collapse
 
fyodorio profile image
Fyodor

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