如何通过 js 函数调用更改 FullCalendar 日期单元格

How to change a FullCalendar day cell via a js function call

当我查看在 FullCalendar 中更改日期单元格的外观或内容的示例时,它们看起来像这样:

    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 class="fa fa-line-chart"  ></i>'+$r.amount+'<br/><i class="fa fa-user" ></i>'+$r.users+'<br/><i class="fa fa-shopping-basket" ></i>'+$r.income);
            }

    }
};

但我需要做的与那个上下文不同。我对 PHP 后端进行 AJAX 调用以 return 假期列表,例如

0 => [
  '2022-05-30',
  'Memorial Day'
]

执行 AJAX 调用的被调用函数将传递一个 FullCalendar 对象。在成功部分,我可以访问日历对象和假期数组。

我需要做的是访问假期日期的单元格并对其进行更改...类似于

let cell = calendar.dayRender('2022-05-30');
cell.css("background-color", "ccf3ff");
cell.text("Memorial Day");

而不是遍历整个日历,将单元格日期与所需日期进行比较。

如果您浏览浏览器的开发工具,检查 Fullcalendar 生成的源代码,您会注意到日历 table 中的每个单元格都有一个带有天数的 data 属性。简化了很多,看起来像这样:

<td ... data-date="2022-04-29" ...>
    <a ... aria-label="April 29, 2022">29</a>
</td>

很容易 select HTML elements by data-attribute:

let el = document.querySelector('[data-date="2022-04-29"]');

在与 Fullcalendar 本身为事件所做的相同位置和格式中添加内容可能是有意义的,这意味着将您的内容放在该单元格的 .fc-daygrid-day-events 元素中。

我在下面包含了一个工作片段,但是通过手动执行此操作,您将必须手动重现 Fullcalendar 为手动呈现事件所做的一切。例如,目前是四月底,因此不会呈现五月前几天(查看四月时显示)之后的任何假期。如果您导航到 May,它们仍然不会被渲染。每当您导航时,您都必须 re-run 您的假期渲染代码。 Fullcalendar 已经为事件自动完成所有这些。

另一个问题是您的文本不会 fit/format 很好地适应当天发生的任何其他事件,例如,如果碰巧有足够多的事件,Fullcalendar 通常会隐藏一些并显示“+ 1更多”,在其中添加假日文本会搞砸。

您还将 运行 陷入样式问题,设置 background-color 将不起作用,除非您使用 !important 因为它与 Fullcalendar 的样式冲突。

如果将假期添加为单独的事件源,则可以避免这一切。您描述它们已经作为 AJAX 提要提供,因此您只需将其添加为 an Event Source,Fullcalendar 将自动处理所有内容。您将不得不更新提要的格式,但这并不难(而且可能是个好主意,因为无论如何在当前的非结构化格式中更难使用)。

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 class="myclass">' + 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/fullcalendar@5.11.0/main.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/main.min.css">

<div id="calendar"></div>