Search code examples
vue.jshtml-tablejavascript-objects

How to loop a list of object in to a table with custom row using Vue.js


im currently develeping a new application by using Vue.js. I have this list of object i take from my db:

list =  [ 
        { "main": "main 1", "sub_main": "sub main 1", "title": "testing", "description": "this is description" },
    { "main": "main 1", "sub_main": "sub main 1", "title": "trying", "description": "this is description 2" }, 
    { "main": "main 1", "sub_main": "sub main 2", "title": "testing again", "description": "this is description" },
    { "main": "main 1", "sub_main": "sub main 2", "title": "still trying", "description": "this is description 2" },
    { "main": "main 2", "sub_main": "sub main 1", "title": "testing another", "description": "this is description" },
    { "main": "main 2", "sub_main": "sub main 2", "title": "i need help", "description": "this is description 2" }
    ] 

I want to loop it with v-for in a table but I need to customize it, so its looks like this

+---------------------+-----------------------+
| Main/Sub Main/Title | Description           |
+---------------------+-----------------------+
|        main 1       |                       |
+---------------------+-----------------------+
|      sub main 1     |                       |
+---------------------+-----------------------+
|       testing       | this is description   |
+---------------------+-----------------------+
|        trying       | this is description 2 |
+---------------------+-----------------------+
|      sub main 2     |                       |
+---------------------+-----------------------+
|    testing again    | this is description   |
+---------------------+-----------------------+
|     still trying    | this is description 2 |
+---------------------+-----------------------+
|        main 2       |                       |
+---------------------+-----------------------+
|      sub main 1     |                       |
+---------------------+-----------------------+
|   testing another   | this is description   |
+---------------------+-----------------------+
|      sub main 2     |                       |
+---------------------+-----------------------+
|     i need help     | this is description 2 |
+---------------------+-----------------------+

currently im just manage to make it every record in one row

 <tr v-for="(data) in list" > 
<td>{{data.main}}</td>
<td>{{data.sub_main}}</td>
<td>{{data.title}}</td>
</tr>

can you guys give me a pointer on how to solve this problem?


Solution

  • first you need to transform your data type into suitable type to loop. I transform your data in computed become like this:

    
    // computed function
    
    computed: {
        sortedList() {
          const sortedList = this.list.reduce((result, item) => {
            const { main, sub_main, title, description } = item;
    
            // check main exists, example: main 1
            if (!result[main]) {
              result[main] = {};
            }
    
            // check sub_main exsts, example: sub main 1
            if (!result[main][sub_main]) {
              result[main][sub_main] = [
                {
                  title,
                  description
                }
              ];
            }
    
            // if exists, add other data
            result[main][sub_main] = [
              ...result[main][sub_main],
              { title, description }
            ];
    
            return result;
          }, {});
          return Object.entries(sortedList);
        }
      }
    
    
    // result
    {
      'main 1':  
      {
        'sub main 1': [
            { title: 'testing', description: 'this is description' }, 
            { title: 'testing', description: 'this is description' }, 
            { title: 'trying', description: 'this is description 2' }
        ], 
        'sub main 2': [
            { title: 'testing again', description: 'this is description' }, 
            { title: 'testing again', description: 'this is description' }, 
            { title: 'still trying', description: 'this is description 2' }
        }, 
      'main 2': { ... }
    } 
    
    

    then I loop in triple v-for in the list I sorted.

    
    <template>
      <div id="app">
        <div class="wrapper" v-for="([mainKey, mainValue], index) in sortedList" :key="index">
          <tr>
            <td>{{mainKey}}</td>
          </tr>
          <template v-for="([submainKey, submainValue], index) in Object.entries(mainValue)">
            <tr :key="index">
              <td>{{submainKey}}</td>
            </tr>
            <tr v-for="({title, description}, index) in submainValue" :key="index">
              <td>{{title}}</td>
              <td>{{description}}</td>
            </tr>
          </template>
        </div>
      </div>
    </template>
    
    

    Screeshot of the result:

    the result screeshot

    The codesandbox is provided in below:

    https://codesandbox.io/s/64o1p6xv4r

    Hope I can solve your problem!