For performance purposes, especially with interactions, I'm trying to convert my fullcalendar component with event sources, rather than grouping all my API calls in a Promise.all and sending an array of events.
The problem is that my sources are promises, and they do send an array in the right format, but the FullCalendar schedule is still empty, and I don't understand why...
Here's my component (simplified):
<FullCalendar
ref={calendarRef}
schedulerLicenseKey={process.env.SCHEDULER_KEY}
plugins={[resourceTimelinePlugin, interactionPlugin]}
initialView='resourceTimelineMonth'
locale="fr"
timeZone="Europe/Paris"
height="100%"
headerToolbar={false}
resources={filteredResources}
eventSources={[
{
//Some parameters depends on react hook states
events: satisfactionSourceEvents(planningType, filteredResources, horizon, draft, execId, parseInt(selectedSolution))
}
]}
nowIndicator
slotDuration= "24:00:00"
eventClick={handleEventClick}
slotLabelContent={HeaderContent}
resourceLabelContent={renderResourceContent}
eventContent={renderEventContent}
dateClick={handleDateClick}
The satisfactionSourceEvents function is in another file :
function satisfactionSourceEvents(planningType: PlanningType, resources: GroupResource[], horizon: any, draft?: PlanningDraft, execId?: number, solId?: number): Promise<any[]>{
let _serviceIds = resources.map(s => s.id)
//API functions with multiple parameters, return timeline object
return TimelineAPI.getTimeline(planningType, planningType === "draft" ? draft.id : null, execId ?? null, solId ?? null, {
serviceIds: _serviceIds.join(),
start: horizon.from.format(DateISOFormat),
end: horizon.to.format(DateISOFormat),
"withDetail.shifts": true,
"withResult.demandSatisfactionMeasuresByShift": true,
"withResult.demandSatisfactionMeasuresGlobal": false,
})
//return a FullCalender events array
.then(timeline => getSatisfactionDemandTimelineAsFCEventObject(timeline.result.demandSatisfactionMeasuresByShift, timeline.detail))
}
When I log the return of satisfactionSourceEvents function, I find my array of events, here's an example, as well as the resources sent to fullCalendar (filteredResources state).
events :
[
{"start": "2023-11-01T00:00:00","end": "2023-11-01T23:59:59", "resourceId": "1_2"}
{"start": "2023-11-02T00:00:00","end": "2023-11-02T23:59:59", "resourceId": "1_2"}
{"start": "2023-11-03T00:00:00","end": "2023-11-03T23:59:59", "resourceId": "1_2"}
...
]
resources :
[
{
"id": 2,
"title": "Service 2",
"resourceType": "SERVICE",
"children": [
{
"id": "1_2",
"title": "N7",
"resourceType": "SHIFT",
},
{
"id": "2_2",
"title": "B12",
"resourceType": "SHIFT",
},
...
]
}
]
The api return format is correct, since it hasn't changed and was working before the switch to eventSources. Is it possible to use Promise in eventSources?
If need be, I can try to make a codepen, but it might take me a long time...
Thank you very much
Fullcalendar doesn't directly accept a Promise as input, no. So what's happening is you're returning the Promise to fullCalendar, but not the events themselves - they don't arrive until the Promise is resolved, and fullCalendar isn't programmed to be able to access them.
As per the events as a function documentation you can wrap your asynchronous request inside the function syntax provided by fullCalendar, and then use the callback passed into it to provide fullCalendar with the downloaded events, once your Promise has resolved.
Something like this:
and
N.B. Bear in mind that the events function will run every time the calendar changes the visible date range, and will refresh with whatever is downloaded from the event source. So ideally, as per the documentation, your event source should make use of the start and end dates provided in the
fetchInfoobject, and use them to only return events which are within (or overlap with) that date range. That means you'll only transmit the events which are actually needed by the user, rather than a potentially much bigger set of events, many of which might never actually be viewed during that session.