2

I'm trying to understand how/if I can define some sort of slot inheritance in Vue.js v3. I have a Container class that defines 2 slots: title and items. I extend Container in my Grid class, and I define the items slot in there. When I go to use my Grid class, I would like to define the title slot. Fiddle for reference.

Container.vue

<template>
  <div>
    <header v-if="showTitle">
      <slot name="title" />
    </header>

    <main v-if="showItems">
      <slot name="items" />
    </main>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "MyContainer",
  computed: {
    showTitle() {
      return !!this.$slots.title;
    },
    showItems() {
      return !!this.$slots.items;
    },
  },
});
</script>

Grid.vue

<template>
  <MyContainer>
    <template #items>
      <span>Here are my items</span>
    </template>
  </MyContainer>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import MyContainer from "@/components/base/Container";

export default defineComponent({
  name: "MyGrid",
  extends: MyContainer,
  components: { MyContainer },
});
</script>

App.vue

<template>
  <div id="app">
    <MyGrid>
      <!-- How can I pass this along to MyGrid's base class? -->
      <template #title>
        <span>This is my title!</span>
      </template>
    </MyGrid>
  </div>
</template>

<script>
import MyGrid from "@/components/base/Grid";

export default {
  name: "App",
  components: {
    MyGrid,
  },
};
</script>

The issue is in App.vue where I have the comment in the template--I would like to pass along defining the slot in there. Is this possible?

0

2 Answers 2

6

According to this, I would have to define a template that essentially passes on any slots defined on the instance. So in my Grid.vue class, I would add this code:

<template>
  <MyContainer>
    <template #items>
      <span>Here are my items</span>
    </template>
    <!-- Added this template -->
    <template v-for="(_, name) in $slots" v-slot:[name]="slotData">
      <slot :name="name" v-bind="slotData" />
    </template>
  </MyContainer>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import MyContainer from "@/components/base/Container";

export default defineComponent({
  name: "MyGrid",
  extends: MyContainer,
  components: { MyContainer },
});
</script>
Sign up to request clarification or add additional context in comments.

Comments

2

In Grid component define the title slot then inside it render its children dynamically using component :

 <MyContainer>
    <template #title>
      <component v-for="(el, i) in $slots.title()" :is="el" :key="i">
      </component>
    </template>
    <template #items>
      <span>Here are my items</span>
    </template>
  </MyContainer>
</template>

DEMO

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.