sveltesveltekitsvelte-componentsvelte-store

How to force svelte component to mount in an {#if} block


I have a sidebar with collapsible sections that use slots like this:

<Sidebar> // creates writable context
   <Searchbar /> // updates context

   <Collapsible>
      <MyControl label="hello" /> // subscribes to context to check if label matches search
      <MyControl label="world" /> // subscribes to context to check if label matches search
   </Collapsible>
</Sidebar>

Sidebar creates a writable context which Searchbar updates and MyControl subscribes to in order to check if it's being searched. My issue is because my controls are in an {#if} block, they don't mount until Collapsible is expanded just 1 time first, and if they don't mount then they never subscribe to the context and my search doesn't work. As soon as the Collapsible section is expanded just 1 time (can be collapsed afterwards) my searchbar works.

Collapsible.svelte:

{#if expanded}
  <div transition:slide>
     <slot />
  </div>
{/if}

My question is basically can i force my <slot /> to mount? or is there some other way to solve this issue?


Solution

  • i have solved it myself using a #key block and the in/out transitions like this:

    {#key expanded}
        <div 
              class={clsx(!expanded && "hidden")}
              in:getAnimation={{fn: slide, cond: expanded}} 
              out:getAnimation={{fn: slide, cond: !expanded}}>
             <slot />
        </div>
    {/key}
    

    where getAnimation is:

     const getInAnimation = (node, options) => {
       if (options.cond) {
         return options.fn(node, options);
       }
     };