0

I am trying to parse a JSON string that my Laravel application serves to my Vue view. The JSON string can look like this:

{  
   "1":[ { "row":"Some text here on first column." },
         { "row":"And more text. Second row." },
         { "row":"Text!" }
   ],
   "2":[ { "row":"2nd column text." },
         { "row":"" }
   ],
   "3":[ { "row":"Even more text. But on the third column." }
   ]
}

Things to note here:

  1. The "1", "2", and "3" refers to columns. So in above examples, I have 3 columns.
  2. Each "row" refers to a row within the column.

I am trying to parse the string as a table, like: https://jsfiddle.net/59bz2hqs/1/

This is what I have now:

<template>
    <div>
      <table>
          <tbody>
              <tr v-for="row in this.content">
                 <td>{{row}}</td>
               </tr>
           </tbody>
      </table>
   <div>
</template>

<script>
    export default {
        data() {
            return {

                content: []
            }
        },
        created() {
            Event.$on("document-was-processed", content => {
                this.content = content;          
            });
        }
    }

</script>

Now above simply prints out the actual JSON string. Can anyone help me out on how to actually parse the content?

Edit

Thinking a bit more about this. I am actually not quite sure if my JSON string layout can even support my desired output.

Maybe like something below? Not quite sure.

{ "1":[
      { "text":"Some text here on first column."},
      { "text":"2nd column text."},
      { "text":"Even more text. But on the third column"}
   ],
   "2":[
      { "text":"And more text. Second row." },
      { "text":"" },
      { "text":"" }
   ],
   "3":[
      { "text":"Text!"},
      { "text":""},
      { "text":""}
   ]}

Then something like:

<table class="text-left w-full border-collapse m-3">
  <thead>
    <tr class="bg-gray-100">

      <th v-for="(item, idx) in this.content" class="p-1">
        {{idx}}
      </th>
    </tr>
  </thead>
  <tbody>
    <tr v-for="(row, rid) in this.content">
      <td v-for="(col, cid) in row">{{ col.text }} </td>
    </tr>
  </tbody>
</table>

1 Answer 1

2

You have to transpose your data before rendering it.

This is my dummy code

<script>
export default {
  data() {
    return {
      dataTable: []
    };
  },
  created() {
    // Instead of fetching your content I put it in a local variable
    let content = JSON.parse(`{  
   "1":[ { "row":"Some text here on first column." },
         { "row":"And more text. Second row." },
         { "row":"Text!" }
   ],
   "2":[ { "row":"2nd column text." },
         { "row":"" }
   ],
   "3":[ { "row":"Even more text. But on the third column." }
   ]
    }`);
    // Transform object in array of its values
    let data = Object.values(content);
    let colsLength = data.map(r => r.length);
    let maxNumCols = Math.max.apply(Math, colsLength);
    let colsArraySchema = Array.apply(null, Array(maxNumCols)).map((r, i) => i);
    this.dataTable = colsArraySchema.map((col, i) => data.map(row => row[i]));

    // For debug.
    console.log(content);
    console.log(data);
    console.log(colsLength);
    console.log(maxNumCols);
    console.log(this.dataTable);
  }
};
</script>

Now you can render the dataTable variable in your template. (Take care that you row array could contain undefined values)

<template>
  <table border="1">
    <tbody>
      <tr v-for="(row, index) in dataTable" :key="index">
        <td v-for="(cell, index) in row" :key="index">
          <span v-if="cell">{{cell["row"]}}</span>
        </td>
      </tr>
    </tbody>
  </table>
</template>

You can see a live demo here: https://codesandbox.io/s/vue-json-transpose-dt915

I hope it helps you.

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

7 Comments

This is very nice! Do you mind checking my edit of my OP? I propose another JSON string format - I am not sure if this is better? The JSON string is created by my backend (PHP, Laravel), so my 2nd JSON string requires me to change a bit of backend code.
Just a question to your answer: I tested with some other content. The console.log(data) returns 1: Array(8), 2: Array(52), 3: Array(33). However, for some reason the console.log(this.dataTable) output is: 0: (3), 1: (3), 2: (3) - for some reason, it only outputs 3 rows? While one of the columns have 52.
Can you share your new JSON content with 52 columns?
using this transpose function seems to give me another output. - this outputs: (8) [Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), Array(3), But this only prints out 8 rows, where I still have a total of 52 in the "longest" column.
Thank you SO much! You've literally freed me from hours and hours of debugging and headbanging! Really appreciate you taking your time to help me out :) It works perfectly!
|

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.