Svelte Component- Add Block field not working as expected in visual Editor

Hi, I am creating a tab component as shown in this documentation (I’m using Svelte) - Adding Children to Custom Components - Builder.io, But I am not able to view add Block section in the visual editor and when I drag and drop any component/block on my tabFields component for a particular tab it gets added throughout all the tabs and on deleting it from a particular tab it gets deleted from all of them, attaching the screenshots and code below for reference.

Screenshots-

now when i drag and drop a particular component on Blog tab it is also getting added to Contact tab and vice versa


This is the response I am getting on consoling the builderBlock props

@type: "@builder.io/sdk:Element"
@version: 2
children: [{…}]
component: 
    name: "TabFields"
    options: 
        tabList: Array(2)
            0: {children: Array(0), tabName: 'Blogs'}
            1: {children: Array(0), tabName: 'Contact'}
            length: 2

Here is my code for TabComponent.svelte:

<script lang="ts">
    import * as BuilderSDK from '@builder.io/sdk-svelte';
    
    export let tabList: any[];
    export let builderBlock:any;
    export let builderContext:any [];
    let activeTab:any = 0;

    function selectTab(tab:any) {
        activeTab = tab;
    }

    $:{console.log("Active Tab", tabList[activeTab], builderBlock, builderContext);}
</script>

<div class="lg:mx-[130px] section-header overflow-hidden">
    <h2 class="mx-4 mb-5 text-3xl bold">Stay up to date</h2>
    <div class="tabs-wrap">
        <button class="hidden">prev</button>
        <div class="tabs flex">
        {#if tabList}
        {#each tabList as tab, index}
        <button
        class="py-6 px-4 border-b-4 border-solid cursor-pointer font-bold text-xl leading-normal whitespace-nowrap text-[#333] {activeTab === index ? 'border-green-500' : 'border-[#fff]'}"
        on:click={() => selectTab(index)}
      >
        {tab.tabName}
      </button>
        {/each}
        {/if}
        </div>
        <button class="hidden">next</button>
    </div>
    {#if tabList && tabList?.length != 0}
        <slot/>
        <BuilderSDK.Blocks
        parent={builderBlock?.id}
        path={`component?.options?.tabList?.${activeTab}.children`}
        blocks={tabList[activeTab]?.children}
        />
      {/if}
</div>

This is how i am registering the component in builder.io

  {
    component: TabSection,
    name: 'TabFields',
    canHaveChildren: true,
	  inputs: [
      {
        name: 'tabList',
        type: 'list',
        subFields: [
          {
            name: 'tabName',
            type: 'string',
          },
          {
            name: 'children',
            type: 'blocks',
            defaultValue: []
          }
        ]
      }
    ]
  }
2 Likes

Hi @manish-sharma, Any resolution on this issue.
Please reply asap for the concerned issue

Hello @Ankit,

Add <slot></slot> wherever you want your children to be. For more detail, visit the Svelte special elements entry on <slot> .

Additionally, try passing the defaultChild and let us know how that works fo you

// Register your Builder components
const REGISTERED_COMPONENTS = [
  {
    component: HelloWorldComponent,
    name: 'Hello World',
    canHaveChildren: true,
    inputs: [
      {
        name: 'text',
        type: 'string',
        defaultValue: 'Hello World',
      },
    ],
    defaultChildren: [
      { 
        '@type': '@builder.io/sdk:Element',
        component: { name: 'Text', options: { text: 'I am child text block!' } }
      }
    ],
  },
];

Hi @manish-sharma ,

I have followed all the steps you mentioned above, but despite that, when I drag and drop a component/block for a particular tab, it is getting added on the same level as the component. As you can see in my builderBlock response above, the length of the children inside the tablist array is still 0, indicating that it does not get added inside the list type. I have also provided the structure of how I am registering my component on Builder.io, along with the code, builderBlock response, and some screenshots above. Could you please look into it?

Hello @Prashant,

Could you please confirm the version of the Builder.io Svelte SDK you are currently using?

Additionally, if you could share the complete updated code, it would be greatly appreciated. This will help us to reproduce the issue on our end and provide a more accurate solution.

Thank you!

yes @manish-sharma, I am using version - 0.12.0 of builder.io Svelte SDK

yes this is my svelte component code which i am using to create a Tab-

<script lang="ts">
    import * as BuilderSDK from '@builder.io/sdk-svelte';
    
    export let tabList: any[];
    export let builderBlock:any;
    export let builderContext:any [];
    let activeTab:any = 0;

    function selectTab(tab:any) {
        activeTab = tab;
    }

    $:{console.log("Active Tab", tabList[activeTab], builderBlock, builderContext);}
</script>

<div class="lg:mx-[130px] section-header overflow-hidden">
    <h2 class="mx-4 mb-5 text-3xl bold">Stay up to date</h2>
    <div class="tabs-wrap">
        <button class="hidden">prev</button>
        <div class="tabs flex">
        {#if tabList}
        {#each tabList as tab, index}
        <button
        class="py-6 px-4 border-b-4 border-solid cursor-pointer font-bold text-xl leading-normal whitespace-nowrap text-[#333] {activeTab === index ? 'border-green-500' : 'border-[#fff]'}"
        on:click={() => selectTab(index)}
      >
        {tab.tabName}
      </button>
        {/each}
        {/if}
        </div>
        <button class="hidden">next</button>
    </div>
    {#if tabList && tabList?.length != 0}
        <slot/>
        <BuilderSDK.Blocks
        parent={builderBlock?.id}
        path={`component?.options?.tabList?.${activeTab}.children`}
        blocks={tabList[activeTab]?.children}
        />
      {/if}
</div>

**This is how i am registering the component and all it fields-

export const CUSTOM_COMPONENTS = [
  {
    component: TabSection,
    name: "TabFields",
    canHaveChildren: true,
    inputs: [
      {
        name: "tabList",
        type: "list",
        subFields: [
          {
            name: "tabName",
            type: "string",
          },
          {
            name: "children",
            type: "blocks",
            defaultValue: [
              {
                "@type": "@builder.io/sdk:Element",
                component: {
                  name: "Text",
                  options: {
                    text: "this is editable within builder ",
                  },
                },
                responsiveStyles: {
                  large: {
                    display: "flex",
                    flexDirection: "column",
                    position: "relative",
                    flexShrink: "0",
                    boxSizing: "border-box",
                    marginTop: "8px",
                    lineHeight: "normal",
                    height: "auto",
                    textAlign: "center",
                  },
                },
              },
            ],
          },
        ],
      },
    ],
  },
];

This is my configuration inside […catchall] route to connect to builder.io

following code is inside routes/[…catchall]/+page.svelte

<script>
  import { isPreviewing, Content } from "@builder.io/sdk-svelte";
  import { CUSTOM_COMPONENTS } from '../../registerComponents/componentsRegistry'

	// this data comes from the function in `+page.server.js`, which runs on the server only
	export let data;

  // we want to show unpublished content when in preview mode.
  const canShowContent = data.content || isPreviewing();
</script>

<svelte:head>
  <title>Home</title>
</svelte:head>

<main>
  {#if canShowContent}
    <Content
      model="page"
      content={data.content}
      apiKey={import.meta.env.VITE_BUILDER_PUBLIC_API_KEY}
      customComponents={CUSTOM_COMPONENTS}
    />
  {:else}
    Content Not Found
  {/if}
</main>

following code is inside routes/[…catchall]/+page.server.js

import { fetchOneEntry, getBuilderSearchParams } from "@builder.io/sdk-svelte";

/** @type {import('./$types').PageServerLoad} */
export async function load(event) {
const content = await fetchOneEntry({
    model: "page",
    apiKey: import.meta.env.VITE_BUILDER_PUBLIC_API_KEY,
    options: getBuilderSearchParams(event.url.searchParams),
    userAttributes: {
      urlPath: event.url.pathname || '/',
    },
  });

  return { content};
}

Hello @Prashant,

Could you upgrade to our latest svelte SDK 1.0.8 and see if that makes any difference? Meanwhile, I’ll try to reproduce the issue on our end using your code

Thank you @manish-sharma after updating svelte SDK to version 1.0.8 my issue got resolved, It is working now.

1 Like