Grouping with <template>
Sometimes a v-if or a v-for should cover several elements at once. You could wrap them in a div, but that isn't always allowed (a ul may only have lis inside it) or wanted (it can upset a layout). Put the directive on a <template> element instead. It groups the elements inside it, and Vue doesn't put the <template> itself on the page:
<template v-if="open">
<h2>Menu</h2>
<p>Fresh coffee and cake every day.</p>
</template>
<p v-else>Sorry, we're closed.</p>While open is true, the page gets just the h2 and the p, with nothing around them. <template v-for> works the same way, with the :key on the <template>:
<template v-for="item in menu" :key="item.id">
<h3>{{ item.name }}</h3>
<p>€{{ item.price }}</p>
</template>And here's something you should never do: put v-if and v-for on the same element, say to show only the items that aren't sold out:
<li v-for="item in menu" v-if="!item.soldOut" :key="item.id">{{ item.name }}</li>Vue checks v-if first, before v-for has made item, so in the condition, item doesn't exist yet. The page stays empty, and the console starts with this warning:
[Vue warn]: Property "item" was accessed during render but is not defined on instance.
at <App>A few lines later comes the error TypeError: Cannot read properties of undefined (reading 'soldOut').
Put the v-for on a <template> around the element instead, and leave the v-if on the element:
<template v-for="item in menu" :key="item.id">
<li v-if="!item.soldOut">{{ item.name }}</li>
</template>Typical mistake: :key on the element inside <template v-for>. The page doesn't run, and the red bar says <template v-for> key should be placed on the <template> tag.
Instructions
- 1
Show only the items that aren't sold out: put the
v-foron a<template>around theli, and give theliav-if. - 2
When the café is closed, hide the heading and the list, and show
<p class="closed">Sorry, we're closed.</p>instead. Group the heading and the list with<template v-if>, so that the page has no element around them.