2

I'm having an issue trying to figure out a v-for loop around an array that I've built, which is in the exact format that I want

The snippet below shows the format of the data, but basically I'm trying to build a table for employees where the table header is made of dates and the employee data is matched by the date.

My issue is that I can't figure out how to loop down to the jobs level and match the data for each table cell to the date in the header

Given the array dumped in the snippet below, I would want something like this:

Employee  |  08/12/2021            |  08/13/2021
----------------------------------------------------------------
Miranda   | Area 1234567           |  Area 1234569
              Job 123 - 10 Hours        Job 184 - 18 Hours
            Area 1234568
              Job 167 - 15 Hours

So basically just matching the array records by employee and date (in table header), and then where there's a match just display the area/job information in the table cell

How can I fix the current v-for loop structure I've started in order to achieve this?

const nest = (rows) =>
  rows .reduce(
    (a, row) => {
      const employee = a [row .employee] || (a [row .employee] = {dates: {}})
      const date = employee .dates [row .job_date] || (employee .dates [row .job_date] = {areas: {}})
      const order = date .areas [row .area_number] || (date .areas [row .area_number] = {jobs: {}})
      const job = order .jobs [row .job] || (order .jobs [row .job] = {hours: '', scans: '', job_date: ''})

      job.hours += row.hours
      job.scans += row.scans
      job.job_date = row.job_date

      return a
    },
    {}
  );

new Vue({
  el: "#app",
  props: { 

  },
  data: {
    rows: [
        {  
            employee: "Miranda",
            job: "123",
            hours: "10",
            job_date: "08/12/2021",
            scans: 37,
            area_number: "1234567",

        },
         {  
            employee: "Miranda",
            job: "167",
            hours: "15",
            scans: 12,
            job_date: "08/12/2021",
            area_number: "1234568",
            
        },
        {  
            employee: "Miranda",
            job: "184",
            hours: "18",
            scans: 24,
            job_date: "08/13/2021",
            area_number: "1234569",
            
        }
    ],
},
computed: {

    numbersByEmployee() { 
      return nest(this.rows)
    },
    dates() {
      const dates = [...new Set(this.rows.map(r => r.job_date))]
      return dates.sort((a,b) => new Date(a) - new Date(b))
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>


<div id="app">

  <table>
  <thead>
      <tr>
       <th>Employee</th>
          <th v-for="date in dates" :key="date">{{ date }}</th>
      </tr>
    </thead>
  <tbody>
    <tr v-for="(areas,employee) in numbersByEmployee" :key="employee">
      <td>{{employee}}</td>
      <td v-for="date in dates" :key="date">
        
      </td>
    </tr>
  </tbody>
  </table>


{{numbersByEmployee}}
</div>

1 Answer 1

1

Just like array, you can also apply v-for to objects. Reference

Syntax

v-for="(value, key) in object"

Working Solution

const nest = (rows) =>
  rows.reduce(
    (a, row) => {
      const employee = a[row.employee] || (a[row.employee] = { dates: {} })
      const date = employee.dates[row.job_date] || (employee.dates[row.job_date] = { areas: {} })
      const order = date.areas[row.area_number] || (date.areas[row.area_number] = { jobs: {} })
      const job = order.jobs[row.job] || (order.jobs[row.job] = { hours: '', scans: '', job_date: '' })

      job.hours += row.hours
      job.scans += row.scans
      job.job_date = row.job_date

      return a
    },
    {}
  );

new Vue({
  el: "#app",
  props: {

  },
  data: {
    rows: [
      {
        employee: "Miranda",
        job: "123",
        hours: "10",
        job_date: "08/12/2021",
        scans: 37,
        area_number: "1234567",

      },
      {
        employee: "Miranda",
        job: "167",
        hours: "15",
        scans: 12,
        job_date: "08/12/2021",
        area_number: "1234568",

      },
      {
        employee: "Miranda",
        job: "184",
        hours: "18",
        scans: 24,
        job_date: "08/13/2021",
        area_number: "1234569",

      }
    ],
  },
  computed: {

    numbersByEmployee() {
      return nest(this.rows)
    },
    dates() {
      const dates = [...new Set(this.rows.map(r => r.job_date))]
      return dates.sort((a, b) => new Date(a) - new Date(b))
    },
  }
});
td,
th {
  border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <table>
    <thead>
      <tr>
        <th>Employee</th>
        <th v-for="date in dates" :key="date">{{ date }}</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(value, name) in numbersByEmployee" :key="name">
        <!-- name will be Miranda-->
        <!-- Value will be dates object-->
        <td>{{name}}</td>
        <td v-for="(dateSpecificData, dateValue) in value.dates" :key="dateValue">
          <div v-for="(areaList, areaKey) in dateSpecificData">
            <div v-for="(area, areaId) in areaList">
              Area {{ areaId }}
              <div v-for="(job, jobId) in area.jobs">
                Job {{ jobId }} - {{job.hours}} Hours
              </div>
            </div>
          </div>
        </td>
      </tr>
    </tbody>
  </table>
</div>

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

1 Comment

Thank you very much for this answer! I see now how easily it's applied whether it's an array or an object

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.