Reputation: 5105
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>
Upvotes: 2
Views: 496
Reputation: 20006
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>
Upvotes: 1