Reputation: 19168
I have an array that looks like this:
var arr = [{
text: '1'
}, {
text: '2'
children: [{
text: '2.1'
}]
}, {
text: '3',
children: [{
text: '3.1'
}, {
text: '3.2',
children: [{
text: '3.2.1'
}, {
text: '3.2.2'
}]
}]
}];
I want to display only the "leafs" of this array in a table, while showing the parents of the leafs. I want to generate the following HTML:
<table>
<tr>
<td>1</td>
</tr>
<tr>
<td>2 | 2.1</td>
</tr>
<tr>
<td>3 | 3.1</td>
</tr>
<tr>
<td>3 | 3.2 | 3.2.1</td>
</tr>
<tr>
<td>3 | 3.2 | 3.2.2</td>
</tr>
</table>
I tried the following, but it doesn't work because the <section>
s are interspersed with the <tr>
s.
<section v-for="parent in arr">
<tr v-if="!parent.children">
<td>{{ parent.text }}</td>
</tr>
<section v-if="parent.children" v-for="child in parent.children">
<tr v-if="!child.children">
<td>{{ parent.text + ' | ' + child.text }}</td>
</tr>
<tr v-if="child.children" v-for="grandchild in child.children">
<td>{{ parent.text + ' | ' + child.text + ' | ' + grandchild.text }}</td>
</tr>
</section>
</section>
Upvotes: 1
Views: 322
Reputation: 55634
In Vue, it's always better to try and simplify your data structure to cater to your display needs than to try and find a roundabout way of displaying your data using directives in the template.
Usually, the best way to simplify your data is via computed properties. As @RoyJ suggested, you can make a computed property which would recursively generate a flattened array from your object's tree structure, and then reference that computed in the template instead.
Here's how I would do it:
new Vue({
el: '#app',
data() {
return {
arr: [{
text: '1'
}, {
text: '2',
children: [{
text: '2.1'
}]
}, {
text: '3',
children: [{
text: '3.1'
}, {
text: '3.2',
children: [{
text: '3.2.1'
}, {
text: '3.2.2'
}]
}]
}]
}
},
computed: {
flatArr() {
let flatArr = [];
let addToFlatArr = ({ items, base }) => {
items.forEach((item) => {
let { text, children } = item;
let val = (base || '') + text;
if (children) {
addToFlatArr({ items: children, base: val + ' | '})
} else {
flatArr.push(val);
}
})
};
addToFlatArr({ items: this.arr });
return flatArr;
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>
<div id='app'>
<table>
<tr v-for="item in flatArr">
<td>{{ item }}</td>
</tr>
</table>
</div>
Upvotes: 2