Named Slots

The panel has one place for content. The menu needs cards with three places: a heading at the top, the price in the middle and a button at the bottom, each in its own part of the card, with lines between them. A component can have several slots when it gives them names. Here's MenuCard.vue:

<template>
    <article class="card">
        <header>
            <slot name="header" />
        </header>
        <div class="body">
            <slot />
        </div>
        <footer>
            <slot name="footer" />
        </footer>
    </article>
</template>

A <slot> without a name is the default slot. The parent fills a named slot with a <template> that has # and the slot's name:

<MenuCard>
    <template #header>
        <h2>Carrot Cake</h2>
    </template>
    <p>€4</p>
    <template #footer>
        <button>Add</button>
    </template>
</MenuCard>

The <template> elements themselves aren't on the page, only their content: the heading goes into the card's header, and the button into its footer. The paragraph isn't in any <template #…>, so it goes into the default slot. The order in the parent doesn't matter: the card's template decides where each part goes.

#header is short for v-slot:header, as @click is short for v-on:click. You'll see both in other code; this course uses #. And the default slot is named default, so its content can also be in a <template #default>.

Why a slot for the heading, when the panel had a prop title? A prop is enough for a short text. Here, the heading also has a label with the category next to the name, and another card could have a picture there. A rule of thumb: data and short texts go into props, pieces of the page into slots. A component can have both, as the panel does.

Typical mistakes:

  • Content for a named slot that isn't in a <template #…>. It goes into the default slot, so it shows in the middle of the card.
  • A different name in the card and in the parent, such as <slot name="footer" /> and <template #foot>. A named slot that nothing fills stays empty, and content for a slot that the card doesn't have isn't shown, both without a warning.
  • # on an element other than <template>, such as <button #footer>. That's a mistake in the file, and the red bar under the preview says where it is and v-slot can only be used on components or <template> tags.

Instructions

  1. In MenuCard.vue, put a slot named header into the header element. In App.vue, put each card's heading into <template #header>.

  2. Do the same for the button: a slot named footer in the card's footer, and the button in <template #footer>.