Cannot use v-for on stateful component root element because it renders multiple elements?
Asked Answered
A

3

31

app.js

var Users = {
    template: `
        <tr v-for="list in UsersData">
            <th>{{ list.idx }}</th>
            <td>{{ list.id }}</td>
        </tr>
    `,
    data: function () {
        return {
            UsersData //get data from query
        }
    }
}

var mainview = new Vue({
    el: "#mainview",
    components: {
        'users': Users
    },
    method: {}
})

layout.blade.php

<body>
    <div class="container">
        <aside>...</aside>
        <main id="mainview">
            @section('content')
            @show
        </mainview>
    </div>
</body>

index.blade.php

@extends('layout')
@section('content')
<table>
    <thead>
        <tr>
            <th>IDX</th>
            <th>ID</th>
        </tr>
    </thead>
    <tbody>
        <users></users>
    </tbody>
</table>
@endsection

ERROR LOG from chrome console

[Vue warn]: Cannot use v-for on stateful component root element because it renders multiple elements:

<tr v-for="list in UsersData">
    <th>{{ list.idx }}</th>
    <td>{{ list.id }}</td>
</tr> 

vue.js:525 [Vue warn]: Multiple root nodes returned from render function. Render function should return a single root node. (found in component )

How should I fix code?

Alphonsoalphonsus answered 26/5, 2017 at 4:48 Comment(0)
P
47

Your template has to have one root element. It's just one rule you cannot break. Since you're making a table, it would make sense to make tbody the root element.

var Users = {
    template: `
        <tbody>
            <tr v-for="list in UsersData">
                <th>{{ list.idx }}</th>
                <td>{{ list.id }}</td>
            </tr>
        </tbody>
    `,
    data: function () {
        return {
            UsersData //get data from query
        }
    }
}

index.blade.php

@extends('layout')
@section('content')
<table>
    <thead>
        <tr>
            <th>IDX</th>
            <th>ID</th>
        </tr>
    </thead>
    <users></users>
</table>
@endsection
Pagas answered 26/5, 2017 at 5:1 Comment(1)
I cannot wrap my template into <thead> or <tbody> because there is not the single <th v-for> loop in my cause but two, first one for special columns, another one for data columns. Wrapping everything into <template> also does not work. – Rawdan
A
37

For the lazy: Vue interprets the root element having a v-for loop on it as producing multiple root level elements (a nono in modern JS frameworks).

Just wrap your template in a superfluous blank <div>. πŸ‘Œ

Anglaangle answered 19/7, 2017 at 20:38 Comment(4)
Adding random <div>s in the middle of the table structure just to keep the framework happy? That doesn't seem like a good idea. – Vannie
I hate the answer. But it worked really well for me haha – Reductase
Adding a <div> worked for me too but why do we need it in vue? – Shama
Why does v-for directive needs a single root element? – Shama
P
1

I struggled with this, until I realized you can just add a section tag over everything in template and then this error goes away. Example

//gives error 

<template> 
  <div classname="allFutures" v-for="(items, index) in arr">
      <Future title="Shee" />
    </div>
</template> 

    // do this instead

<template>
  <section id="main" class="main-alt">
    <div classname="allFutures" v-for="(items, index) in arr">
      <Future title="Shee" />
    </div>
  </section>
</template>
Proteolysis answered 13/7, 2022 at 11:51 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.