[Vuejs]-Vue v-for nested array

-1👍

What you need is two diferent iterations. One for the header and another for the table body. For the header, all you need is to add the month name on order. The snippet shows with the computed property months how to do it. This completes the header iteration and the first.

The second one is a little more complex. You need to know beforehand how many lines there will be, for that I made a computed property maxLength that searches over each md and gives the greater one. Then for each row iterate over each month and then verify if the month has enough dates with v-if and if it does look up the desired date from the index and the nested data sctructure. That resumes the second iteration.

The below snippet is a working example with a more complex data showing what could happen with different md sizes and automatic month ordering.

var app = new Vue({
  el: '#app',
  data: () => ({
    nested: [
      { "dd": "February",
        "md": [{ "dag": "2020-02-01" },{ "dag": "2020-02-02" },{ "dag": "2020-02-03" },{ "dag": "2020-03-04" }]
      },
      { "dd": "March",
        "md": [{ "dag": "2020-03-01" },{ "dag": "2020-03-02" },{ "dag": "2020-03-03" }]
      },
      { "dd": "January",
        "md": [{ "dag": "2020-01-01" }]
      }
    ]
  }),
  computed: {
    staticMonths() {
      return Array.from(Array(12),(e,i)=>new Date(25e8*++i).toLocaleString('en-US',{month: 'long'}));
    },
    months() {
      return this.nested.map(item => item.dd).sort((a, b) => {
        const A = this.staticMonths.indexOf(a);
        const B = this.staticMonths.indexOf(b);
        return A-B;
      });
    },
    maxLength() {
      return this.nested.reduce((accum, curr) => accum > curr.md.length ? accum : curr.md.length, 0);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <table>
    <thead>
      <tr>
        <th v-for="(item, index) in months">{{ item }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="index in maxLength">
        <td v-for="item in months">
          <span v-if="nested.find(nest => nest.dd === item).md.length > index-1">
            {{nested.find(nest=>nest.dd===item).md[index-1].dag}}
          </span>
        </td>
      </tr>
    </tbody>
  </table>
</div>

0👍

You could use a different way to create the loop (one table, multiple columns)
In this case, to populate each header with ‘dd’ and each column with md elements.

var data=[ 
   { 
      "dd":"February",
      "md":[ 
         { 
            "dag":"2020-02-01"
         },
         { 
            "dag":"2020-02-02"
         },
         { 
            "dag":"2020-02-03"
         }
      ]
   },
   { 
      "dd":"March",
      "md":[ 
         { 
            "dag":"2020-03-01"
         },
         { 
            "dag":"2020-03-02"
         },
         { 
            "dag":"2020-03-03"
         }
      ]
   }
];

new Vue({
	el:'#app',
  data:{
    md2s: data
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.8/vue.js"></script>
<div id=app >
<table  >
  <thead >  
         <tr align="center">
          <th v-for="(md2, index) in md2s" :key=index  style="width: 80px">{{md2.dd}}</th>
          </tr>
  </thead>
  <tbody>
    <tr  align="center">
      <td v-for="(md2, index) in md2s" :key=index style="width: 80px">
         <div v-for="(mdcol, col) in md2.md" :key=col>
         {{mdcol.dag}}
         </div> 
      </td>
    </tr>    
  </tbody>
</table>
</div>

https://jsfiddle.net/bn5g1v09/1/

Leave a comment