Symptoms
While working on a VueJS component, you face the following error in your browser console (or in your JS linter output):
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
As explained, VueJS component templates can contain one and only one root node. This is correct:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
This is not:
<template>
<div class="hola">
<h1>{{ msg }}</h1>
</div>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
Fix
Wrap your html tags into one parent element:
<template>
<div>
<div class="hola">
<h1>{{ msg }}</h1>
</div>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</div>
</template>
Going further
In some case, you cannot afford to add an extra parent element without breaking HTML structure. For instance, if your child component template replace several <tr> in a parent HTML table:
<template>
<tr class="hola">
...
</tr>
<tr class="hello">
...
</tr>
</template>
In this specific case, you need have two solutions:
- use functional components ;
- use Fragments (my favorite one)
Fragments let you group multiple children below a parent element without adding extra nodes to the DOM at render. There is a vue-fragment package you can install:
npm install vue-fragments // yarn add vue-fragments
While loading VueJS:
import { Plugin } from "vue-fragments"; Vue.use(Plugin);
Then in your component template:
<template>
<v-fragment>
<tr class="hola">
...
</tr>
<tr class="hello">
...
</tr>
<v-fragment>
</template>
Hope it helps!