'Customizing Day Cell content in FullCalendar
I am using fullcalendar with react. I am trying to customize the dayGrid view. According to the Content Injection docs for react I can use custom content for the rendering of both the date and the header cells. The dayCellContent "hook" states that:
Generated content is inserted inside the inner-most wrapper of the day cell. It does not replace the cell.
I've provided an implementation for the dayCellContent and noticed that my content gets injected into the following structure:
<td class="fc-daygrid-day fc-day fc-day-wed fc-day-past rot_time-off_day-cell" data-date="2021-04-07">
<div class="fc-daygrid-day-frame fc-scrollgrid-sync-inner">
<div class="fc-daygrid-day-top">
<a class="fc-daygrid-day-number">
...custom content goes here
</a>
</div>
<div class="fc-daygrid-day-events"></div>
<div class="fc-daygrid-day-bg"></div>
</div>
</td>
Now, the problem is that this structure lets you insert content ONLY in the upper right corner of the date cell due to the positioning of the element. Furthermore, it is in an anchor element.
Example:
function renderDayCell(dayCellContent: DayCellContentArg) {
return (
<div>
{dayCellContent.dayNumberText}
</div>
);
}
Is there a clean way to customize the whole content of the cell somehow? I've seen a couple of sites using fullcalendar that have their content inserted directly into the td. Not sure if this is version dependent or they're using the alternative JS approach based on domNodes or html. I am using version 5.6.0 of fullcalendar.
Solution 1:[1]
I had the same requirement although not using React. I solved it using a manual manipulation of the DOM elements as suggested above. I have used jQuery for the select and manipulation. It is posted here in case anyone would like to see an example of how this can be achieved using DOM manipulation.
I implemented dayCellContent to make the day-cell DOM element easily identifiable by wrapping it in a span, with a unique id attribute based on the day of year number:
dayCellContent: function(info, create) {
const element = create('span', { id: "fc-day-span-"+info.date.getDayOfYear() }, info.dayNumberText);
return element;
},
This dayCellContent implementation makes no visible difference to the calendar but makes it easier to identify the elements to be modified in the DOM.
I then implemented dayCellDidMount to do the DOM manipulation by finding the appropriate cells and selecting their parent’s parent:
dayCellDidMount: function(info) {
let element = "<div style='position: absolute; left: 4px; top: 4px;'><a href='https://www.w3schools.com/'>TEST-"+info.dayNumberText+"</a></div>";
$('#fc-day-span-'+info.date.getDayOfYear()).parent().parent().prepend(element);
},
In this case I have just put a link to w3c in the top left of the cell with test text which also includes the day number. It results in cells that look like this:
Clearly the CSS could be improved and should be moved out to the CSS definitions but it illustrates the point.
Warning: This approach makes assumptions about the DOM structure that FullCalendar generates. The generated HTML may change in future versions of the product which could invalidate it. If you go this way then be careful when doing a FullCalendar update.
Note that the getDayOfYear function is from the ext-all.js library. Any way of uniquely identifying the day will work.
Solution 2:[2]
ngAfterViewInit(){
// Your CSS as text
var styles =.fc td, .fc th { vertical-align: top; padding: 0; height: 100px; } a{ color:#3d1cba; }
let styleSheet = document.createElement("style");
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
let arrTD = document.querySelectorAll('td.fc-timeline-slot');
let arrTR= document.querySelectorAll('td.fc-timeline-lane.fc-resource');
let arrInject= document.querySelectorAll('td.fc-timeline-lane.fc-resource>div.fc-timeline-lane-frame');
console.log(arrTR);
let k=-1;
arrTR.forEach(eachTR => {
let i=1;
let str = '';
k++;
let data_resource_id= eachTR.getAttribute('data-resource-id');
console.log(data_resource_id);
arrTD.forEach(eachTD => {
let k=100*(i-1);
i=i+1;
let data_date= eachTD.getAttribute('data-date');
console.log(data_date);
let data_resource_id= eachTR.getAttribute('data-resource-id');
console.log(data_resource_id);
str = str + '<span data-date="'+data_date+'" data-resource-id="'+data_resource_id+'" class="plus_icon" style="position:relative;top: 0px; left: '+k+'px !important;width:500px;height:500px;z-index:3;-moz-border-radius:100px;border:1px solid #ddd;-moz-box-shadow: 0px 0px 8px #fff;">+</span>';
});
arrInject[k].innerHTML=str;
});
let elementList = this.elRef.nativeElement.querySelectorAll('span.plus_icon');
for(let i=0;i<elementList.length;i++){
elementList[i].addEventListener('click', this.plusClick.bind(this));
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Amirul Momenin |


