1

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>
1
  • 2
    Make a computed that recursively descends the tree and yields a simple array. It will be easy to render that. Commented Jan 18, 2018 at 21:48

1 Answer 1

2

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>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.