Reputation: 1713
I have 2 components.
The table component calls the row component inside the <tbody>
tag for every row in the data.
But while rendering the rows are rendered first (outside the table tag) followed by the <table>
tag.
See the example below.
Vue.component('single-table-row', {
props: {
row: {
type: Object
}
},
template: `
<tr>
<td>{{row.id}}</td>
<td>{{row.text}}</td>
</tr>
`
});
Vue.component('mytable', {
props: {
tabledata: {
type: Object
}
},
data: function () {
return {
headers: ['Id', 'Text']
}
},
computed: {
table_rows: function () {
return this.tabledata.data.rows;
}
}
});
var app3 = new Vue({
el: '#app-3',
data: {
mydata: {
data: {
rows: [
{
id: 1,
text: 'Sample 1'
},
{
id: 2,
text: 'Sample 2'
},
{
id: 3,
text: 'Sample 3'
}
]
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app-3">
<mytable v-bind:tabledata="mydata" inline-template>
<div id="table_parent">
<table>
<thead>
<tr>
<th v-for="header in headers">{{header}}</th>
</tr>
</thead>
<tbody>
<single-table-row :row=rows v-for="rows in table_rows" :key=rows.id>
</single-table-row>
</tbody>
</table>
</div>
</mytable>
</div>
The output is rendered as :
<div id="table_parent">
<tr>
<td>2</td>
<td>Sample 2</td>
</tr>
<tr>
<td>1</td>
<td>Sample 1</td>
</tr>
<tr>
<td>3</td>
<td>Sample 3</td>
</tr>
<table>
<thead>
<tr>
<th>Id</th>
<th>Text</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
Ideally it should have rendered the row component inside the <tbody>
tag.
What am I missing here ?
Upvotes: 2
Views: 335
Reputation: 29092
You need to use <tr is="single-table-row"
instead of <single-table-row
.
https://v2.vuejs.org/v2/guide/components.html#DOM-Template-Parsing-Caveats
This is because your template is directly in the HTML. The browser will parse it before Vue gets anywhere near it. Certain elements, such as tbody
, have restrictions on what child elements they can have. Any elements that are not allowed will be torn out the table. By the time Vue gets involved they've already been moved.
Vue.component('single-table-row', {
props: {
row: {
type: Object
}
},
template: `
<tr>
<td>{{row.id}}</td>
<td>{{row.text}}</td>
</tr>
`
});
Vue.component('mytable', {
props: {
tabledata: {
type: Object
}
},
data: function () {
return {
headers: ['Id', 'Text']
}
},
computed: {
table_rows: function () {
return this.tabledata.data.rows;
}
}
});
var app3 = new Vue({
el: '#app-3',
data: {
mydata: {
data: {
rows: [
{
id: 1,
text: 'Sample 1'
},
{
id: 2,
text: 'Sample 2'
},
{
id: 3,
text: 'Sample 3'
}
]
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app-3">
<mytable v-bind:tabledata="mydata" inline-template>
<div id="table_parent">
<table>
<thead>
<tr>
<th v-for="header in headers">{{header}}</th>
</tr>
</thead>
<tbody>
<tr is="single-table-row" :row=rows v-for="rows in table_rows" :key=rows.id>
</tr>
</tbody>
</table>
</div>
</mytable>
</div>
Upvotes: 2