Recursive Components in Vue 3 using Slots

You might find various use cases of Recursive Vue Components where the Source is based on some Nested Array. What we are going to demonstrate here is Recursive Element Implementation from Tags. Let's say we want to create a Sidebar for Admin Panel and want to make it look minimal in coding.

<sidebar-item name="Dashboard" link="#">
  <sidebar-item name="Dashboard Default" link="/dashboard"></sidebar-item>
  <sidebar-item name="Dashboard eCommerce" link="/dashboard-ecommerce"></sidebar-item>
</sidebar-item>
<sidebar-item name="Components" link="/components"></sidebar-item>

Actual implementation of each sidebar item would be more like this:

<li class="nav-item">
  <a class="nav-link" href="#"><span class="nav-link-text">Dashboard</span></a>
</li>

To achieve this we will make use of Vue slots. We will be creating a SidebarItem.vue Component.

<template>
  <li class="nav-item">
    <a class="nav-link" :href="link">
      <span class="nav-link-text">{{ name }}</span>
    </a>
    <div class="nav-item-inner" v-if="childrenExists">
      <slot></slot>
    </div>
  </li>
</template>
<script>
export default {
  name: "sidebar-item",
  props: {
    name: {
      type: String,
    },
    link: {
      type: String,
    },
  },
  computed: {
    childrenExists() {
      if (this.$slots.default) {
        return !!this.$slots.default;
      } else {
        return false;
      }
    },
  },
};
</script>

In above code <slot></slot> will make sure than inner components will be automatically processed. Method childrenExists makes sure to disable nav-item-inner if inner components is empty.

<sidebar-item name="Dashboard" link="#">
  <sidebar-item name="Dashboard Default" link="/dashboard"></sidebar-item>
  <sidebar-item name="Dashboard eCommerce" link="/dashboard-ecommerce"></sidebar-item>
</sidebar-item>
<sidebar-item name="Components" link="/components"></sidebar-item>
.
.
.
// Import SidebarItem component
import SidebarItem from "@/components/SidebarItem.vue";

Vue.component("sidebar-item", SidebarItem);

Output would be

<li class="nav-item">
  <a class="nav-link" href="#"><span class="nav-link-text">Dashboard</span></a>
  <div class="nav-item-inner">
    <li class="nav-item">
      <a class="nav-link" href="/dashboard"><span class="nav-link-text">Dashboard Default</span></a>
    </li>
    <li class="nav-item">
      <a class="nav-link" href="/dashboard-ecommerce"><span class="nav-link-text">Dashboard eCommerce</span></a>
    </li>
  </div>
</li>
<li class="nav-item">
  <a class="nav-link" href="/components"><span class="nav-link-text">Components</span></a>
</li>

Leave a Reply

Your email address will not be published. Required fields are marked *


The reCAPTCHA verification period has expired. Please reload the page.