oliverbj
oliverbj

Reputation: 6062

Vue/PHP - Parse JSON string as table

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>

Upvotes: 0

Views: 495

Answers (1)

Stefano Giraldi
Stefano Giraldi

Reputation: 1309

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.

Upvotes: 2

Related Questions