babis95
babis95

Reputation: 622

How to use v-for to dynamically display data table with nested loops

I have a table component called from my entry file. The Table component gets the documents object passed on as prop. Inside the table component I have a table which should render the object data one under another in order the data comes in. Each row should have the User name, Document name, and date of view. (Please see bottom of the question for current & expected result). I am facing the issue because the object is structured in a way that the views are nested inside the parent, and I don't know how to loop over the outer object to get into the inner one without affecting the layout (Hence the use of <span>)

Object:

data() {
    return {
      documents: [
        {
          id: 1,
          name: "Doc 1",
          date: "01.01.1995",
          doc_website: "linktodocument1.com",
          views: [
            {
              id: 4,
              user_name: "Jon",
              doc_id: 1,
              view_date: "01.02.1996",
            },
            {
              id: 1,
              user_name: "Bob",
              doc_id: 1,
              view_date: "05.02.1996",
            },
          ],
        },
        {
          id: 2,
          name: "Doc 2",
          date: "01.01.2000",
          doc_website: "linktodocument2.com",
          views: [
            {
              id: 1,
              user_name: "Bob",
              doc_id: 2,
              view_date: "01.02.1996",
            },
            {
              id: 1,
              user_name: "Jon",
              doc_id: 2,
              view_date: "05.02.1996",
            },
          ],
        },
        {
          id: 3,
          name: "Doc 3",
          date: "01.01.2000",
          doc_website: "linktodocument3.com",
          views: [
            {
              id: 1,
              user_name: "Bob",
              doc_id: 3,
              view_date: "01.02.1996",
            },
            {
              id: 1,
              user_name: "Jon",
              doc_id: 3,
              view_date: "05.02.1996",
            },
            {
              id: 3,
              user_name: "Rob",
              doc_id: 3,
              view_date: "05.02.1996",
            },
          ],
        },
      ],
    };
  },

Entry File:

<template>
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Document</th>
        <th>Date</th>
      </tr>
    </thead>
    <table-component :docObject="documents"></table-component>
  </table>
</template>

<script>
import tableComponent from "./table.vue";

export default {
  components: { tableComponent },
}
</script>

Component:

<template>
  <tbody>
    <span v-for="doc in docObject" :key="doc.name">
      <td v-for="view in doc.views" :key="view.id">
        <p>
          {{ view.user_name }}
        </p>
      </td>
      <td>
        <p>
          {{ doc.name }}
        </p>
      </td>
      <td v-for="view in doc.views" :key="view.name">
        <p>
          {{ view.view_date }}
        </p>
      </td>
    </span>
  </tbody>
</template>

<script>
export default {
  components: {},
  props: ["docObject"],
};
</script>

<style scoped>
td {
  padding: 15px 15px;
  border: 1px solid black;
}
</style>
Current Output: 
Name                                                   Document Date      
Jon Bob Doc 1 1.02.1996 05.02.1996
Bob Jon Doc 2 01.02.1996 05.02.1996
Bob Jon Rob Doc 3 01.02.1996 05.02.1996 05.02.1996

Expected Result:
Name             Document           Date
Jon               Doc 1            1.02.1996
Bob               Doc 1            05.02.1996
Bob               Doc 2            01.02.1996
Bob               Doc 2            05.02.1996
Bob               Doc 3            01.02.1996
Jon               Doc 3            05.02.1996
Rob               Doc 3            05.02.1996

Codesandbox link: https://codesandbox.io/s/zealous-cerf-rfmf2?file=/src/components/table.vue:0-585

Upvotes: 1

Views: 1146

Answers (1)

Ben
Ben

Reputation: 2255

You should use template instead of span and there is no need to complicate it further with multiple td tags, it can be simple as this:

<template>
  <tbody>
    <template v-for="doc in docObject">
      <tr v-for="view in doc.views" :key="view.id">
        <td>{{ view.user_name }}</td>
        <td>{{ doc.name }}</td>
        <td>{{ view.view_date }}</td>
      </tr>
    </template>
  </tbody>
</template>

<script>
export default {
  components: {},
  props: ["docObject"],
};
</script>

<style scoped>
td {
  padding: 15px 15px;
  border: 1px solid black;
}
</style>

Please check this codesanbox: https://codesandbox.io/s/nice-ives-b33u5?file=/src/components/table.vue

Output:

enter image description here

Upvotes: 2

Related Questions