To add an icon to a day, we need to identify the grid we want to add an icon to. For instance, today, past days, future days, weekends only, etc. Then we add the icon through JavaScript.
There are two ways to do that:
- Identify the cell to add an icon to inside the
dayCellDidMount
render hook, and add the icon - Right After calendar render, select the cell element(s) through the combination of classes using
querySelectorAll
and add the icon to it/them
Here’s the calendar with a plus icon on all future days.
Here’s how to add it, using both methods.
Using dayCellDidMount
dayCellDidMount render hook gives us arg
object, which has el
in it that we can use to manipulate or add to the required cell.
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
dayCellDidMount : function(arg){
if(arg.el.classList.contains("fc-day-future")){
var theElement = arg.el.querySelectorAll(".fc-daygrid-day-frame > .fc-daygrid-day-events")[0]
setTimeout(function(){
if(theElement.querySelectorAll(".fc-daygrid-event-harness").length === 0){ // check there's no event
theElement.innerHTML = theElement.innerHTML + '<div class="text-center"><i class="calendar-icon fas fa-plus"></i></span></div>';
}
}, 10)
}
}
});
calendar.render();
});
In case of events present on any of the days, we don’t want to show plus icon. For that, we check the existence of the .fc-daygrid-event-harness
class inside the element, because it won’t be present on event-less days. Notice that this check is wrapped in setTimeout
. It’s because .fc-daygrid-event-harness
is always empty initially at the time dayCellDidMount
is called.
Using querySelectorAll
The same thing as above can be done by identifying all the elements using document.querySelectorAll
without using any hook.
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
var selectedDays = document.querySelectorAll('.fc-day-future > .fc-daygrid-day-frame > .fc-daygrid-day-events');
for(var i = 0; i < selectedDays.length; ++i){
if(selectedDays[i].querySelectorAll(".fc-daygrid-event-harness").length === 0){ // check there's no event
selectedDays[i].innerHTML = selectedDays[i].innerHTML + '<div class="text-center"><i class="calendar-icon fas fa-plus"></i></span></div>';
}
}
});
We loop over future days by selecting them through .fc-day-future > .fc-daygrid-day-frame > .fc-daygrid-day-events
selector.
Notice there’s a downside to this method. We only add icons on the initial render. So if we move between months by clicking today, next, or prev, the icons won’t appear in future months, and the current icons will vanish too.
To overcome this, we add a listener to .fc-button
, which will be fired on clicking today, next, and prev, and call addIcon
from inside of it. addIcon
is a method where we move our original logic. We also call this method once outside click listener for initial rendering.
We also need to add an extra check to look for existing .fa-plus
, or else multiple icons will appear on some days.
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
function addIcon(){
var selectedDays = document.querySelectorAll('.fc-day-future > .fc-daygrid-day-frame > .fc-daygrid-day-events');
for(var i = 0; i < selectedDays.length; ++i){
if(selectedDays[i].querySelectorAll(".fc-daygrid-event-harness").length === 0 &&
selectedDays[i].querySelectorAll(".fa-plus").length === 0){
selectedDays[i].innerHTML = selectedDays[i].innerHTML + '<div class="text-center"><i class="calendar-icon fas fa-plus"></i></span></div>';
}
}
}
document.querySelectorAll('.fc-button').forEach(function(el){
el.addEventListener('click', function() {
addIcon()
});
});
addIcon();
});
In both cases above, text-center
is a bootstrap class to center the icon (Tailwind’s text-center
will work the same), and calendar-icon
is a class to change icon font and color.
.calendar-icon {
font-size: 14px;
color: lightgray;
}
The fontawesome can be replaced with glyphicon icon too:
selectedDays[i].innerHTML = selectedDays[i].innerHTML +
'<div class="text-center"><span class="calendar-icon glyphicon glyphicon-plus"></span></div>';
Other Selectors
Below are some useful query selectors examples for conditionally adding icons. That can be replaced in either of the methods mentioned above.
- Mondays
if(arg.el.classList.contains("fc-day-mon")) {
//...
}
// OR
document.querySelectorAll('.fc-day-mon > .fc-daygrid-day-frame > .fc-daygrid-day-events');
- Future Mondays
if(arg.el.classList.contains("fc-day-mon") && arg.el.classList.contains("fc-day-future")) {
//...
}
//OR
document.querySelectorAll('.fc-day-mon.fc-day-future > .fc-daygrid-day-frame > .fc-daygrid-day-events');
- Past Mondays
if(arg.el.classList.contains("fc-day-mon") && arg.el.classList.contains("fc-day-past")) {
//...
}
// OR
document.querySelectorAll('.fc-day-mon.fc-day-past > .fc-daygrid-day-frame > .fc-daygrid-day-events');
- Weekends
if(arg.el.classList.contains("fc-day-sun") || arg.el.classList.contains("fc-day-sun")) {
//...
}
// OR
document.querySelectorAll('.fc-day-sun,fc-day-sat > .fc-daygrid-day-frame > .fc-daygrid-day-events');
Add Multiple Icons On Different Days
For this, we need to get select multiple elements with different conditions and add our icons of choice. Using the second method, let’s add a cross icon on past days, and a plus on future days.
The code would be:
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth'
});
calendar.render();
function addIcon() {
var futureDays = document.querySelectorAll('.fc-day-future > .fc-daygrid-day-frame > .fc-daygrid-day-events');
for (var i = 0; i < futureDays.length; ++i) {
if (futureDays[i].querySelectorAll(".fc-daygrid-event-harness").length === 0 &&
futureDays[i].querySelectorAll(".fa-plus").length === 0) {
futureDays[i].innerHTML = futureDays[i].innerHTML + '<div class="text-center"><i class="calendar-icon fas fa-plus"></i></span></div>';
}
}
var pastDays = document.querySelectorAll('.fc-day-past > .fc-daygrid-day-frame > .fc-daygrid-day-events');
for (var i = 0; i < pastDays.length; ++i) {
if (pastDays[i].querySelectorAll(".fc-daygrid-event-harness").length === 0 &&
pastDays[i].querySelectorAll(".fa-times").length === 0) {
pastDays[i].innerHTML = pastDays[i].innerHTML + '<div class="text-center"><i class="calendar-icon fas fa-times"></i></span></div>';
}
}
}
document.querySelectorAll('.fc-button').forEach(function(el){
el.addEventListener('click', function() {
addIcon()
});
});
addIcon();
});