When I look at examples of changing the appearance or contents of a day cell in FullCalendar, they look like this:
calendar: {
height: 650,
editable: true,
header: {
left: '',
center: 'prev title next',
right: ''
},
defaultView: 'month',
dayRender: function (date, cell) {
$r = $scope.getDateInfo(date);
if($r){
cell.css("background-color", "#ccf3ff");
}
cell.html('<i ></i>' $r.amount '<br/><i ></i>' $r.users '<br/><i ></i>' $r.income);
}
}
};
But what I need to do differs than that context. I make an AJAX call to a PHP back end to return a list of holidays, like
0 => [
'2022-05-30',
'Memorial Day'
]
The called function doing the AJAX call gets passed a FullCalendar object. In the success section I have access to both the calendar object and the array of holidays.
What I need to be able to do is get access to the cell for the holiday date and make changes to it... something akin to
let cell = calendar.dayRender('2022-05-30');
cell.css("background-color", "ccf3ff");
cell.text("Memorial Day");
rather than looping through the entire calendar comparing the cell date to the desired date.
CodePudding user response:
If you poke about in your browser's devtools, inspecting the source that Fullcalendar generates, you'll notice that every cell in the calendar table has a data
attribute with the days date. Much simplified, it looks like this:
<td ... data-date="2022-04-29" ...>
<a ... aria-label="April 29, 2022">29</a>
</td>
It is easy enough to select HTML elements by data-attribute:
let el = document.querySelector('[data-date="2022-04-29"]');
It probably make sense to add content in the same place and format as Fullcalendar itself does for events, that would mean placing your content inside the .fc-daygrid-day-events
element in that cell.
I've included a working snippet below, but by doing this manually, you will have to manually reproduce everything Fullcalendar does for rendering events manually as well. As an example, it is currently the end of April, so any holidays beyond the first few days of May (which show up when viewing April) will not be rendered. If you navigate to May, they still won't be rendered. You have to re-run your holiday rendering code whenever you navigate. Fullcalendar already does all this automatically for events.
Another issue is your text won't fit/format well with any other events that happen to be on that day, and if eg there happen to be enough that Fullcalendar would normally hide some and show " 1 more", adding the holiday text there will mess that up.
You'll also run into styling issues, setting the background-color
won't work unless you use !important
as it clashes with Fullcalendar's styling.
You could avoid all this if you add your holidays as a separte event source. You describe they are already available as an AJAX feed, so you can simply add that as an Event Source, and Fullcalendar will handle everything automatically. You will have to update the format of your feed, but that's not hard (and probably a good idea anyway, as it is harder to use in its current unstructured format anyway).
let holidays = [
['2022-04-29', 'Today'],
['2022-05-01', 'May Day'],
['2022-05-30', 'Memorial Day']
];
function addHolidays() {
let cell, events;
for (const holiday of holidays) {
cell = document.querySelector('[data-date="' holiday[0] '"]');
if (cell) {
events = cell.getElementsByClassName('fc-daygrid-day-events')[0];
events.insertAdjacentHTML('beforeend', '<div >' holiday[1] '</div>');
cell.style.setProperty("background-color", "red", "important");;
}
}
}
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
addHolidays();
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]/main.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/main.min.css">
<div id="calendar"></div>