[Vuejs]-How can I work around the limitation of multiple root elements in Vue.js?

1👍

Thanks to @AlexMA I was able to solve my problem by using a functional component. Here is what it looks like:

import SortableItemContent from './SortableItemContent.vue';

export default {
  functional: true,
  props: {
    tree: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  render(createElement, { props }) {
    const flat = [];

    function flatten(data, depth) {
      const depthRef = typeof depth !== 'undefined' ? depth + 1 : 0;

      data.forEach((item, index) => {
        const itemCopy = item;

        itemCopy.index = index;
        itemCopy.depth = depthRef;
        itemCopy.indentation = new Array(depthRef);

        flat.push(itemCopy);

        if (item.children.length) {
          flatten(item.children, depthRef);
        }
      });
    }

    flatten(props.tree);

    return flat.map((element) => createElement('div', {
      attrs: {
        'data-index': element.index,
        'data-depth': element.depth,
        class: 'sortable-item',
      },
    },
    [
      createElement(SortableItemContent, {
        props: {
          title: element.title,
          indentation: element.indentation,
        },
      }),
    ]));
  },
};

The SortableItemContent component looks like this:

<template>
  <div class="item-content">
    <div
      v-for="(item, index) in indentation"
      :key="index"
      class="item-indentation"
    ></div>
    <div class="item-wrapper">
      <div class="item-icon"></div>
      <div class="item-title">{{ title }}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'SortableItemContent',
  props: {
    title: String,
    indentation: Array,
  },
};
</script>

Given the data I have posted on my question, it now renders the HTML elements like I wanted:

<div data-index="0" data-depth="0" class="sortable-item">
  <div class="item-content">
    <div class="item-wrapper">
      <div class="item-icon"></div>
      <div class="item-title">Header</div>
    </div>
  </div>
</div>
<div data-index="0" data-depth="1" class="sortable-item">
  <div class="item-content">
    <div class="item-indentation"></div>
    <div class="item-wrapper">
      <div class="item-icon"></div>
      <div class="item-title">Paragraph</div>
    </div>
  </div>
</div>
<div data-index="1" data-depth="0" class="sortable-item">
  <div class="item-content">
    <div class="item-wrapper">
      <div class="item-icon"></div>
      <div class="item-title">Container</div>
    </div>
  </div>
</div>
<div data-index="0" data-depth="1" class="sortable-item">
  <div class="item-content">
    <div class="item-indentation"></div>
    <div class="item-wrapper">
      <div class="item-icon"></div>
      <div class="item-title">Paragraph</div>
    </div>
  </div>
</div>

Thank you again @AlexMA for the tip on Functional Components.

Leave a comment