skip to Main Content

I’m looking at the example on Vue.js documentation for iteratively rendering a Tree using the v-for directive. My goal was to alter the code to iteratively render multiple TreeItems in the App.vue file.

My question is why can you iteratively render TreeItem by passing down a list of children objects in the ‘TreeItem.vue’ file, but when trying to iteratively render TreeItem in App.vue, it does not render multiple tree objects within a list. Reading over the docs, the v-for mentions it renders ‘element or template block’ but seems inconsistent with how it’s being called in ‘TreeItem.vue’.

Any explanation to help my understanding is greatly appreciated!

Link to original code example: https://vuejs.org/examples/#tree

I was getting stuck trying use v-for within the TreeItem component like so:

const listOfTrees = ref([{
  name: 'My Tree 2',
  children: [
    { name: 'hello' },
    { name: 'world' },
    {
      name: 'child folder',
      children: [
        {
          name: 'child folder',
          children: [{ name: 'hello' }, { name: 'world' }]
        },
      ]
    }
  ]
},{
  name: 'My Tree',
  children: [
    { name: 'hello' },
    { name: 'world' },
    {
      name: 'child folder',
      children: [
        {
          name: 'child folder',
          children: [{ name: 'hello' }, { name: 'world' }]
        },
        { name: 'hello' },
        { name: 'world' },
        {
          name: 'child folder',
          children: [{ name: 'hello' }, { name: 'world' }]
        }
      ]
    }
  ]
}
])


<template>
  <ul>
    <TreeItem class="item" f-for="tree in listOfTrees" :model="treeData"></TreeItem>
  </ul>
</template>

I did get something to work where I wrapped the ‘outer’ ul in a div and iteratively rendered the div’s:

<template>
  <!-- Wrapped the entire ul in a div and iterate the div's -->
  <div v-for= "tree in listOfTrees">
    <ul>
        <TreeItem class="item" :model="tree"></TreeItem>
    </ul>
  </div>
</template>

This result was what I was expecting during the first approach. I’m curious as to why the second attempt was successful and the first was not.

2

Answers


  1. Hmmm. first of all there is a typeo, so f-for should be v-for.

    Also, template goes like this:

    <template>
      <ul>
        <TreeItem class="item" v-for="(tree, index) in listOfTrees" :model="tree" :key="index"></TreeItem>
      </ul>
    </template>
    

    So, iteration goes like this on vue.

    Don’t hesitate if you need more explanation.

    Login or Signup to reply.
  2. You probably should reorganize the Tree using only objects (this will 
    simplify the recursion of the component), but it is for your case:
    Tree Component
    
    <template>
    <div class="flexCol">
      <template v-for="item in listOfTrees">
         <template v-for="(value, key) in item">
            <div v-if="key === 'name'" class="group">Name: {{value}}</div>
            <template v-else-if="key === 'children'">
               <Menutree :menuPart="value"></Menutree>
            </template>
         </template>
      </template>
    </div>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    import Menutree from './Menutree'
    
    const listOfTrees = ref( [{
      name: 'My Tree 2',
      children: [
         {name: 'hello1'},
         {name: 'world1'},
         {
            name: 'child of My Tree 2',
            children: [
               {
                  name: 'child 1 of child of My Tree 2',
                  children: [{name: 'hello'}, {name: 'world'}]
               },
            ]
         }
      ]
    }, {
      name: 'My Tree',
      children: [
         {name: 'hello'},
         {name: 'world'},
         {
            name: 'child of My Tree ',
            children: [
               {
                  name: 'child 1  of child of My Tree',
                  children: [{name: 'hello'}, {name: 'world'}]
               },
               {name: 'hello'},
               {name: 'world'},
               {
                  name: 'child 2  of child of My Tree',
                  children: [{name: 'hello'}, {name: 'world'}]
               }
            ]
         }
      ]
    }
    ])
    </script>
    
    <style scoped>
    .flexCol {
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: flex-start;
    }
    .group {
      width: 10rem;
      text-align: center;
      background-color: #97e6f3;
      padding: 0.25rem 0;
      margin: 0.25rem;
    }
    
    </style>
    
    Module - Menutree 
    <template>
    <div class="flexCol">
      <template v-for="item in menuPart">
         <template v-for="(valueBase, keyBase) in item">
            <div v-if="keyBase === 'name'" style="margin-left: 3rem" 
            class="subGroup">Name: {{valueBase}}</div>
            <template v-else-if="keyBase === 'children'">
               <template v-for="subitem in valueBase">
                  <div v-if="subitem['name']" style="margin-left: 6rem" 
                  class="subSubGroup">SubName: {{subitem['name']}}</div>
                  <Menutree :menuPart="subitem['children']" style="margin- 
                   left:6rem; background-color: lightyellow"></Menutree>
               </template>
            </template>
         </template>
      </template>
    </div>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    
    defineProps(['menuPart'])
    
    </script>
    
    <style scoped>
    .flexCol {
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: flex-start;
    }
    .subGroup {
      width: auto;
      text-align: left;
      background-color: #f4e1cc;
      padding: 0.25rem;
      margin: 0.25rem 3rem;
    }
    .subSubGroup {
      width: auto;
      text-align: left;
      background-color: #d6f4cc;
      padding: 0.25rem;
      margin: 0.25rem 6rem;
    }
    </style>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search