Reputation: 61
Using this hierarchy of components in vue.js app:
<Root>
<Table>
<Row>
<Row>
...
<Row>
The poblem is with root element in Row component. At first it was table TR element. But now I don't know how many TR rows will be in Row component. Template tag can't be root element.
How it's better to organize Row controller with many TR rows?
<script type="text/template" id="row-template">
<tr>
<td>{{row.name}}</td>
<td>{{row.price}}</td>
</tr>
<tr>
<td>-</td>
<td>{{row.params[0].name}}</td>
</td>
<tr>
<td>-</td>
<td>{{row.params[1].name}}</td>
</td>
</script>
Upvotes: 3
Views: 2319
Reputation: 43881
In addition to the multiple-tbody
trick, it will be necessary to use the is
attribute with a tbody
tag to instantiate the component so that you don't have a component tag where it is not legal.
new Vue({
el: "#foo",
components: {
componentName: {
props: ['first'],
template: '#cn-template'
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<template id="cn-template">
<tbody>
<tr>
<td>{{first}}</td>
</tr>
<tr>
<td>two</td>
</tr>
</tbody>
</template>
<table id="foo">
<tbody>
<tr>
<td>Parent</td>
</tr>
</tbody>
<tbody is="componentName" first="one">
</tbody>
</table>
Upvotes: 3
Reputation: 853
Multiple <tbody/>
is a very good answer but sometimes it's not enough.
For a similar question I purpose an other answer : Vue js error: Component template should contain exactly one root element
copy paste here :
if, for any reasons, you don't want to add a wrapper (in my first case it was for <tr/>
components), you can use a functionnal component.
Instead of having a single components/MyCompo.vue
you will have few files in a components/MyCompo
folder :
components/MyCompo/index.js
components/MyCompo/File.vue
components/MyCompo/Avatar.vue
With this structure, the way you call your component won't change.
components/MyCompo/index.js
file content :
import File from './File';
import Avatar from './Avatar';
const commonSort=(a,b)=>b-a;
export default {
functional: true,
name: 'MyCompo',
props: [ 'someProp', 'plopProp' ],
render(createElement, context) {
return [
createElement( File, { props: Object.assign({light: true, sort: commonSort},context.props) } ),
createElement( Avatar, { props: Object.assign({light: false, sort: commonSort},context.props) } )
];
}
};
And if you have some function or data used in both templates, passed them as properties and that's it !
I let you imagine building list of components and so much features with this pattern.
Upvotes: 0
Reputation: 1022
It's actually valid html to have multiple <tbody>
tags in a table so you could have that be your root element for each component.
<script type="text/template" id="row-template">
<tbody>
<tr>
<td>{{row.name}}</td>
<td>{{row.price}}</td>
</tr>
<tr>
<td>-</td>
<td>{{row.params[0].name}}</td>
</td>
<tr>
<td>-</td>
<td>{{row.params[1].name}}</td>
</tr>
</tbody>
</script>
Upvotes: 2