I'm trying to implement the Timeline calendar from Fullcalendar with Vuejs, but the calendar is initializing before the data is ready. It works if I navigate to other pages and comeback.. all the data is there. I've created the methods: getEmployees() and getApprovedAbsences(), to create the array with the data needed. I'm fairly new to Vue js, so any help would be appreciated. Thanks
Code:
<template>
<div class="admin-calendar">
<FullCalendar :options="calendarOptions" />
</div>
</template>
<script>
import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction'
import resourceTimelinePlugin from '@fullcalendar/resource-timeline'
import ptLocale from '@fullcalendar/core/locales/pt';
import moment from "moment";
export default {
components: { FullCalendar },
props: {
getAbsencesRequests: {
type: Array,
},
employees: {
type: Array,
},
},
data() {
return {
calendarOptions: {
plugins: [ resourceTimelinePlugin ],
headerToolbar: {
left: 'today prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth'
},
locales: [ ptLocale ],
locale: 'pt',
aspectRatio: 1.6,
initialView: 'resourceTimelineDay',
resourceGroupField: 'department',
resourceAreaHeaderContent: 'Colaboradores',
handleWindowResize: false,
height: 400,
resources: this.getEmployees,
events: this.getApprovedAbsences,
}
}
},
methods: {
async getApprovedAbsences() {
let absenceList = []
this.getAbsencesRequests.forEach(absence => {
if (absence.status === "APPROVED") {
absence.periods.forEach((period) => {
absenceList.push({
start: moment(period.validFromLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
end: moment(period.validToLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
title: absence.absenceName,
resourceId: absence.requesterId,
});
});
}
})
return absenceList
},
async getEmployees() {
let employeeList = []
this.employees.forEach(employee => {
employeeList.push({
id: employee.id,
department: employee.department["id"] === "" ? "SEM DEPARTAMENTO ATRIBUÍDO" : employee.department["name"],
title: employee.name,
})
})
return employeeList
}
},
}
</script>
You could add an if statement to check if data is ready. Something like this:
<template>
<div class="admin-calendar">
<FullCalendar
v-if="employeeList && absenceList"
:options="calendarOptions" />
</div>
</template>
This would only load FullCalendar component after resources and events are not null.
Now, change data
to this:
data() {
return {
employeeList: null,
absenceList: null,
calendarOptions: {
plugins: [ resourceTimelinePlugin ],
headerToolbar: {
left: 'today prev,next',
center: 'title',
right: 'resourceTimelineDay,resourceTimelineWeek,resourceTimelineMonth'
},
locales: [ ptLocale ],
locale: 'pt',
aspectRatio: 1.6,
initialView: 'resourceTimelineDay',
resourceGroupField: 'department',
resourceAreaHeaderContent: 'Colaboradores',
handleWindowResize: false,
height: 400,
resources: this.getEmployees,
events: this.getApprovedAbsences,
}
}
}
And change load methods to store data in component variables:
methods: {
async getApprovedAbsences() {
let tmpAbsenceList = []
this.getAbsencesRequests.forEach(absence => {
if (absence.status === "APPROVED") {
absence.periods.forEach((period) => {
tmpAbsenceList.push({
start: moment(period.validFromLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
end: moment(period.validToLocaleDate, "DD/MM/YYYY").format("YYYY-MM-DD"),
title: absence.absenceName,
resourceId: absence.requesterId,
});
});
}
})
absenceList = tmpAbsenceList
},
async getEmployees() {
let tmpEmployeeList = []
this.employees.forEach(employee => {
tmpEmployeeList.push({
id: employee.id,
department: employee.department["id"] === "" ? "SEM DEPARTAMENTO ATRIBUÍDO" : employee.department["name"],
title: employee.name,
})
})
employeeList = tmpEmployeeList
}
},
And finally, call getMethods within created()
:
async created() {
await this.getApprovedAbsences()
await this.getEmployees()
}
This should load everything first, and then call FullCalendar. It should guarantee that everything is set up before loading the component. Try it and check if this idea works for you...