Yes, it is possible to implement this in Vue
and using Vuetify
. You just need to use the computed property to transform the headers and actual rows.
If you look at the vuetify's datatable documentation, it takes headers as an array of text
, value
pair. So it implies, we need to transform our data such a way that vuetify can understand it.
To begin with, just assign the the record to a variable named logs in the data section.
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
logs: []
};
},
Inside the mounted or created hooks, we can initialize the data by some actual data which may come from an API request.
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
logs: []
};
},
computed: {
//will see how to implement this
},
methods: {
getLogs() {
return [
{
employee_id: "E0001",
dtr: [
{
type: "timein",
time: "8:00 am"
},
{
type: "timeout",
time: "5:00 pm"
},
{
type: "timein",
time: "8:30 pm"
},
{
type: "timeout",
time: "8:45 pm"
},
{
type: "timein",
time: "10:45 pm"
}
]
},
{
employee_id: "E0002",
dtr: [
{
type: "timein",
time: "8:00 am"
},
{
type: "timeout",
time: "5:00 pm"
}
]
},
{
employee_id: "E0003",
dtr: [
{
type: "timeout",
time: "5:00 pm"
},
{
type: "timein",
time: "8:00 am"
}
]
}
];
},
initLogs() {
this.logs = this.getLogs();
}
},
created() {
//init log can be use fetch data API with a little bit of change
this.initLogs();
}
});
Now the most important part the computed properties that will construct the actual data required by datatable.We need a computed property for headers and items.
Here is the logHeader computed property that returns employee_id
and timein
and timeout
header rows.
logHeaders() {
// tranforms the logs to find out which is the longest row
let logRecords = this.logs.map((log) => {
let dtrTypes = [];
log.dtr.forEach((d) => dtrTypes.push(d.type));
return {
employee_id: log.employee_id,
dtrLength: log.dtr.length,
dtrTypes: dtrTypes
};
});
let records = _.sortBy(logRecords, ["dtrLength"]);
// find the longest record
let longestRecord = records[records.length - 1];
let headers = [];
console.log("records: ", records[records.length - 1]);
//construct the header row
headers.push({
text: "employee_id",
value: "employee_id"
});
// inside object we can only store unique keys!!
//index plays a crucial role in this as it changes
// timein to be timein1. timein2 so on
longestRecord.dtrTypes.forEach((type, index) =>
headers.push({ text: type, value: type + "" + index })
);
console.log("headers", headers);
return headers;
},
This would give us an array of object like following
[
{ name: 'employee_id', value: 'employee_id' },
{ name: 'timein', value: 'timein' },
{ name: 'timeout', value: 'timeout' }
]
NOTE: As object can't have a duplicate key, If there is another timein entry this would create issue, so we just need to add index to the header values so that we can add more timein
or timeout
with a different value like timin1
or timeout1
.
So the above function uses index to add same key text but with a different value.
[
{ name: "employee_id", value: "employee_id" },
{ name: "timein", value: "timein0" },
{ name: "timeout", value: "timeout1" },
{ name: "timein", value: "timein2" } // here
];
Finally,the logRows
computed property that transforms the logs
array to the kind of data we need for our datatable.
logRows() {
let logR = this.logs.map((log) => {
let dtrRecord = {};
// construct the rows accroding to headers
log.dtr.forEach(
// index is also crucial here
(d, index) => (dtrRecord[d.type + "" + index] = d.time)
);
return Object.assign(
{},
{ employee_id: log.employee_id, ...dtrRecord }
);
});
return logR;
}
In the view we just need to use this headers
and rows
as inputs to the datatable.
<div>
<v-data-table :headers="logHeaders" :items="logRows"></v-data-table>
</div>
If you connect all the bits and pieces together, it would look like following.
new Vue({
el: "#app",
vuetify: new Vuetify(),
data() {
return {
logs: []
};
},
computed: {
logHeaders() {
// tranforms the logs to find out which is the longest
// row
let logRecords = this.logs.map((log) => {
let dtrTypes = [];
log.dtr.forEach((d) => dtrTypes.push(d.type));
return {
employee_id: log.employee_id,
dtrLength: log.dtr.length,
dtrTypes: dtrTypes
};
});
let records = _.sortBy(logRecords, ["dtrLength"]);
// find the longest record
let longestRecord = records[records.length - 1];
let headers = [];
console.log("records: ", records[records.length - 1]);
//construct the header row
headers.push({
text: "employee_id",
value: "employee_id"
});
// inside object we can only store unique keys!!
//index plays a crucial role in this as it changes
// timein to be timein1. timein2 so on
longestRecord.dtrTypes.forEach((type, index) =>
headers.push({ text: type, value: type + "" + index })
);
console.log("headers", headers);
return headers;
},
logRows() {
let logR = this.logs.map((log) => {
let dtrRecord = {};
// construct the row accroding to headers
// checkour
log.dtr.forEach(
(d, index) => (dtrRecord[d.type + "" + index] = d.time)
);
return Object.assign(
{},
{ employee_id: log.employee_id, ...dtrRecord }
);
});
return logR;
}
},
methods: {
getLogs() {
return [
{
employee_id: "E0001",
dtr: [
{
type: "timein",
time: "8:00 am"
},
{
type: "timeout",
time: "5:00 pm"
},
{
type: "timein",
time: "8:30 pm"
},
{
type: "timeout",
time: "8:45 pm"
},
{
type: "timein",
time: "10:45 pm"
}
]
},
{
employee_id: "E0002",
dtr: [
{
type: "timein",
time: "8:00 am"
},
{
type: "timeout",
time: "5:00 pm"
}
]
},
{
employee_id: "E0003",
dtr: [
{
type: "timein",
time: "8:00 am"
},
{
type: "timeout",
time: "5:00 pm"
}
]
}
];
},
initLogs() {
this.logs = this.getLogs();
}
},
created() {
this.initLogs();
}
});
Here is a working codepen to just see this implementation in action.