You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PrimeFaces v8升级至v10:Schedule组件自定义扩展函数失效

PrimeFaces v10 Schedule 自定义扩展回调失效问题

我之前在PrimeFaces v8中使用Schedule组件的自定义扩展函数,实现节假日标记、事件样式定制、日期范围限制等功能,代码运行正常。但升级到内置FullCalendar v5的PrimeFaces v10后,扩展函数里的所有回调都不再触发。我已经查阅过PrimeFaces和FullCalendar的迁移指南,尝试适配FullCalendar v5的Day-cell渲染钩子和Event渲染钩子,但修改回调名称后问题仍未解决,希望能得到帮助。


原Schedule组件代码

<p:schedule id="myCal"
             value="#{calendar.value}"
             leftHeaderTemplate="today"
             rightHeaderTemplate="prev next"
             clientTimeZone="local"
             centerHeaderTemplate="title"
             draggable="false"
             showHeader="true"
             initialDate="#{calendar.initialDate}"
             tooltip="true"
             style="width:100%"
             styleClass="myCal"
             extender="schedulerExt">
</p:schedule>

原自定义扩展函数代码

function schedulerExt() {
    this.cfg.views = {
        month: {
            displayEventEnd: true
        }
    },

    this.cfg.dayRender = function (info) {
        var hol = isHoliday(info.date);
        if (hol >= 0) {
            info.el.classList.remove('fc-past');
            info.el.classList.remove('fc-day');
            info.el.classList.remove('fc-sun');
            info.el.classList.add('holiday');
            info.el.classList.add(getHolidayStyle(hol));
            info.el.setAttribute('title', getHoliday(hol));
            var moment = new Date(info.date);
            MyDateString = moment.getFullYear() + '-' + ('0' + (moment.getMonth() +1) ).slice(-2) + "-" +('0' + moment.getDate()).slice(-2);

            $('[data-date='+MyDateString+']').css({"color": "red", "font-weight":"bold"});
        } else {
            var schoolHol = isSchoolHoliday(info.date);
            if (schoolHol >= 0) {
                info.el.classList.remove('fc-past');
                info.el.classList.remove('fc-day');
                info.el.classList.remove('fc-sun');
                info.el.classList.add('school-holiday');
                info.el.setAttribute('title', 'School Holiday');
                var moment = new Date(info.date);
                MyDateString = moment.getFullYear() + '-' + ('0' + (moment.getMonth() +1) ).slice(-2) + "-" +('0' + moment.getDate()).slice(-2);

                $('[data-date='+MyDateString+']').css({"font-weight":"bold"});
            }
        }
    },

    this.cfg.datesRender = function (info) {
        var minDate = moment().add(-2, 'year');
        var maxDate = moment().add(1, 'year');
        if (minDate >= info.view.activeStart && minDate <= info.view.activeEnd) {
            $('.fc-prev-button').prop('disabled', true);
            $('.fc-prev-button').addClass('fc-state-disabled');
        } else {
            $('.fc-prev-button').removeClass('fc-state-disabled');
            $('.fc-prev-button').prop('disabled', false);
        }
        if (maxDate >= info.view.activeStart && maxDate <= info.view.activeEnd) {
            $('.fc-next-button').prop('disabled', true);
            $('.fc-next-button').addClass('fc-state-disabled');
        } else {
            $('.fc-next-button').removeClass('fc-state-disabled');
            $('.fc-next-button').prop('disabled', false);
        }
    },

    this.cfg.eventRender = function (info) {
        info.el.setAttribute('title', info.event.extendedProps.description);
        if (info.event.title.indexOf("PENDING") !== -1) {
            var spanElement = (function() { var span = document.createElement('span'); span.className = 'fa fa-share-square-o'; span.textContent = '\u00A0'; return span; })();
            info.el.querySelector(".fc-title").innerHTML = info.el.querySelector(".fc-title").innerHTML.replace('PENDING', '');
            info.el.querySelector(".fc-title").parentNode.insertBefore(spanElement, info.el.querySelector(".fc-title"));
        } else {
            if (info.event.title.indexOf("Childcare") !== -1) {
                var spanElement = (function() { var span = document.createElement('span'); span.className = 'fa fa-child'; span.textContent = '\u00A0'; return span; })();
                info.el.querySelector(".fc-title").parentNode.insertBefore(spanElement, info.el.querySelector(".fc-title"));
             } else if (info.event.title.indexOf("Annual") !== -1) {
                 var spanElement = (function() { var span = document.createElement('span'); span.className = 'fa fa-plane'; span.textContent = '\u00A0'; return span; })();
                info.el.querySelector(".fc-title").parentNode.insertBefore(spanElement, info.el.querySelector(".fc-title"));
             }
         }
    };
}

适配PrimeFaces v10 + FullCalendar v5的修改方案

FullCalendar v5对回调钩子、参数结构和DOM元素类名做了大量变更,结合PrimeFaces v10的Schedule组件特性,需要对扩展函数做以下关键修改:

1. 替换废弃的回调函数名称

FullCalendar v5废弃了旧版回调,需替换为新的钩子:

  • dayRender → dayCellDidMount
  • datesRender → 推荐用validRange配置替代(更符合官方API)
  • eventRender → eventDidMount

2. 调整回调参数结构

v5的回调参数和旧版有差异:

  • info.date 为Moment对象,可直接调用format()或toDate()转换为原生Date
  • 无需手动移除旧的FullCalendar类名,直接添加自定义类即可

3. 优化日期范围限制逻辑

v5推荐使用validRange配置替代手动禁用按钮,自动处理日期边界的按钮状态

修改后的完整扩展函数代码

function schedulerExt() {
    // 配置视图选项
    this.cfg.views = {
        month: {
            displayEventEnd: true
        }
    };

    // 替换dayRender为dayCellDidMount
    this.cfg.dayCellDidMount = function(info) {
        var date = info.date;
        var hol = isHoliday(date.toDate()); // 转换为原生Date适配原有方法
        if (hol >= 0) {
            info.el.classList.add('holiday', getHolidayStyle(hol));
            info.el.setAttribute('title', getHoliday(hol));
            // v5单元格自带YYYY-MM-DD格式的data-date属性
            $('[data-date=' + date.format('YYYY-MM-DD') + ']').css({"color": "red", "font-weight":"bold"});
        } else {
            var schoolHol = isSchoolHoliday(date.toDate());
            if (schoolHol >= 0) {
                info.el.classList.add('school-holiday');
                info.el.setAttribute('title', 'School Holiday');
                $('[data-date=' + date.format('YYYY-MM-DD') + ']').css({"font-weight":"bold"});
            }
        }
    };

    // 使用validRange替代datesRender,自动限制日期范围
    this.cfg.validRange = function() {
        return {
            start: moment().add(-2, 'year').toDate(),
            end: moment().add(1, 'year').toDate()
        };
    };

    // 替换eventRender为eventDidMount
    this.cfg.eventDidMount = function(info) {
        info.el.setAttribute('title', info.event.extendedProps.description);
        var titleElement = info.el.querySelector('.fc-event-title');
        if (!titleElement) return;

        if (info.event.title.indexOf("PENDING") !== -1) {
            var spanElement = document.createElement('span');
            spanElement.className = 'fa fa-share-square-o';
            spanElement.textContent = '\u00A0';
            titleElement.textContent = titleElement.textContent.replace('PENDING', '');
            titleElement.parentNode.insertBefore(spanElement, titleElement);
        } else if (info.event.title.indexOf("Childcare") !== -1) {
            var spanElement = document.createElement('span');
            spanElement.className = 'fa fa-child';
            spanElement.textContent = '\u00A0';
            titleElement.parentNode.insertBefore(spanElement, titleElement);
        } else if (info.event.title.indexOf("Annual") !== -1) {
            var spanElement = document.createElement('span');
            spanElement.className = 'fa fa-plane';
            spanElement.textContent = '\u00A0';
            titleElement.parentNode.insertBefore(spanElement, titleElement);
        }
    };
}

额外注意事项

  • 确保项目已引入FullCalendar v5所需的依赖(如Moment.js)
  • PrimeFaces v10的Schedule组件自动加载FullCalendar核心,若使用额外插件需确认依赖完整性
  • 可通过浏览器控制台打印this.cfg,确认配置是否正确传递给FullCalendar实例

内容的提问来源于stack exchange,提问作者Walking body

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:17:02