I'm currently facing a framework shortage with Vue that would be a nice to have. I know it's complex but it would be good to have it appointed maybe for a future.
The idea is to enable to iterate through a list if items and within those items iterate through a list of subitems, but when rendering all of them, put them all at the same level.
Here's an example:
<table>
<!-- item -->
<tr></tr>
<-- subitems -->
<tr></tr>
<tr></tr>
<tr></tr>
</table>
And the js data would be something like:
items: [
{key1: 'val1', subitems: [ {subkey1: 'subval1' }]},
{key1: 'val1', subitems: [ {subkey1: 'subval1' }]},
{key1: 'val1', subitems: [ {subkey1: 'subval1' }]}
]
So there are multiple options to address this issue, some of them without changing Vue.
Without changing Vue:
1) Use <div> and a grid layout to create a table look and feel.
Not possible by requirement. We need to use <tr>
2) Add all items and its subitems sequentially in an array and access it via a computed property. Something like "flattening" the list.
Little dirty as it would require some v-if conditioning in the layout in case the subitems have different keys than the items.
Changing Vue:
1) Allow multiple parent nodes for components so that when rendering. This way I can define a component as:
<item-row></item-row>
and the template would look like:
<tr class="item-row">...</tr>
<tr v-for="subitem in item.subitems>...</tr>
Of course the item would be passed as a prop of the component.
Here's a fiddle with the problematic:
https://jsfiddle.net/ehjmmoat/
Allow multiple parent nodes for components
This won't happen anytime in the forseeable future. The requirement for a root node is deeply rooted (no pun intended) in the way the virtual DOM and component system works. Changing this would practically require a rewrite of a major part of the framework.
Therefore, I will close this issue.
About your problem: The best approach would probably be to use a computed property. The "nasty v-if's" could prevented by normalizing the id names and mayber add a "type" property to tell top items from sub items.
Alternatively, you could consider to wrap this in a functional component, which can return multiple root nodes (because, beingg a functional component, it has no component instance)
If you need further help, please post on our forum: forum.vuejs.org
Also note, that you can use template tag (but this example will only work with single file components, due to html parsing caveats):
<table>
<template v-for="item in list">
<tr>{{ item.title }}</tr>
<tr v-for="subitem in item.subitems">{{ subitem.title }}</tr>
</template>
</table>
Alternatively, you could consider to wrap this in a functional component, which can return multiple root nodes (because, being a functional component, it has no component instance)
@LinusBorg Should this also work in single files components ?
I'm getting an error (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.) with:
<template functional>
<div class="form-field">
</div>
<div class="form-field">
</div>
</template>
Most helpful comment
Also note, that you can use
templatetag (but this example will only work with single file components, due to html parsing caveats):