Home > Mobile >  svelte recursively create treeview from unknown object
svelte recursively create treeview from unknown object

Time:05-05

I am coding some kind of primitive CMS just for editing, updating and adding new strings of an app. the strings are all stored in a database and each of them have a special key (representing the folderstructure of the project "shared.atoms.copie...") for referencing from the sourcecode to the database. the editing stuff and so on is already coded, but now i need to provide the user some kind of navigation and the possibility to see a preview of the page, which is being edited, by clicking (for example) a node of the navigation

for that i want to build a treeview of the already from all keys built object which looks like the following:

tree: {
  common: {
    date: [{
      lang: "en", 
      key: "common.date", 
      version: 1, 
      value: "Date"
    },
    block: {
      lang: "en", 
      key: "common.block", 
      version: 3, 
      value: "Block"
    }]
  },
  shared: {
    atoms: {
      copyClipboard: {
        copiedToClipboard: [{
           lang: "en", 
           key: "shared.atoms.copyClipboard.copiedToClipboad", 
           version: 3, 
           value: "Copied to Clipboard!"
        }]
      }
    }
  }
}

in javascript i got this solution what does give me a tree, when i use {@html htmlTree}:

function buildHtmlTree(treeNode) {
  let objKeys = Object.keys(treeNode);
  if (objKeys.length == 0) {
    return;
  }
  for (let key of objKeys) {
    let currentNode = treeNode[key];
    htmlTree  = `
      <ul >
        <span>
          ${key}
        </span>
      `;
    if (Array.isArray(currentNode)) {
      // is leaf
      for (let currentLanguage of currentNode) {
        htmlTree  = `
          <li >
            ${currentLanguage.lang}: ${currentLanguage.value}
          </li>
          `;
      }
    } else {
      // is branch
      buildHtmlTree(currentNode);
    }
    htmlTree  = `</ul>`;
  }
}

buildHtmlTree(tree);

now i am trying to make it the svelte-way, but i'm stuck at this ... i think i just made an infinite-loop.

<script>
  let svelteTree = Object.keys(tree);
</script>

<section>
  {#each svelteTree as key}
    <ul >
      <span>{key}</span>
      {#if Array.isArray(svelteTree[key])}
        {#each svelteTree[key] as currentLanguageSvelte}
          {currentLanguageSvelte.lang}: {currentLanguageSvelte.value}
        {/each}
      {:else}
        <svelte:self svelteTree={svelteTree[key]} />
      {/if}
    </ul>
  {/each}
</section>

CodePudding user response:

If the values are not an Array nor an Object, you can just output it without calling svelte:self:

{#each Object.entries(data) as [key, values]}
 <ul >
  <span>{key}:</span>
  {#if Array.isArray(values)}
    {#each values as item}
      <svelte:self data={item} />
    {/each}
  {:else if (typeof values === 'object')}
    <svelte:self data={values} />
  {:else}
    <span>{values}</span>
  {/if}
 </ul>
{/each}

Working example

  • Related