componentschildrensvelte-5

In Svelte 5 how do you access children passed to a component?


In Svelte 5 how do you access children passed to a component?

+page.svelte

  <Gallery>    
    <Image src="https://www.renovatorsparadise.com.au/wp-content/uploads/2024/08/p927-768x1152.jpg"  
    url="http://www.google.com" title="Door title 1"/>

    <Image src="https://www.renovatorsparadise.com.au/wp-content/uploads/2024/08/p927-300x450.jpg"  
    url="http://www.yart.com.au" title="Door title 2"/>
  </Gallery>

How do I access the <Image> children in the Gallery?

<script>
  import Image from "./Image.svelte";

  let { children } = $props();    
</script>

<p>The gallery contains {???} images</p>

<p>The first images is {????.url} </p>

Note: I do not want to {@render children()}

I want native access of what is passed


Solution

  • You can't.

    Snippet contents can be highly dynamic and can contain nothing and anything at all.
    In situations where components are tightly coupled, a common approach is to use a shared context.

    I.e. the Gallery would declare a context that Image instances can register themselves in.

    E.g.

    <!-- gallery.svelte -->
    <script>
      import { setContext } from 'svelte';
    
      let { children } = $props();
      let images = $state([]);
      setContext('gallery', images);
    </script>
    
    <p>Image count: {images.length}</p>
    {#if images.length > 0}
      <p>First URL: {images[0].src}</p>
    {/if}
    
    {@render children()}
    
    <!-- image.svelte -->
    <script>
      import { getContext, onDestroy } from 'svelte';
    
      let { src } = $props();
    
      const gallery = getContext('gallery');
      const img = {
        get src() {
          return src;
        }
      };
      gallery.push(img);
    
      onDestroy(() => gallery.splice(gallery.indexOf(img), 1));
    </script>
    
    <img {src} ... >
    

    The logic interacting with the context could also be made conditional, in case an <Image> is used independently of a <Gallery>.