Laravel模态框中FullCalendar无法选择日期问题排查
Laravel项目中模态框内FullCalendar初始无法选择日期的问题排查与解决
问题描述
在Laravel项目里,点击输入框会弹出包含FullCalendar的Bootstrap模态框,但打开模态框后无法直接选择日期,必须点击切换月份按钮后才能正常选择日期。已尝试调整FullCalendar配置项和模态框的z-index属性,均未解决问题。
相关代码
JavaScript代码
var calendarEl = document.getElementById('calendario'); calendar = new FullCalendar.Calendar(calendarEl, { showNonCurrentDates: true, locale: 'es', selectable: true, editable: true, eventColor: 'red', eventTextColor: '#fff', height: 'auto', buttonText: { today: 'Hoy', }, eventOverlap: false, dateClick: function (info) { // 获取日历中选中的日期 var fechaSeleccionada = info.dateStr; // 更新输入框的值为选中的日期 document.getElementById("fechaCita").value = fechaSeleccionada; }, dayCellContent: function (info) { info.dayNumberText = info.dayNumberText.replace(/^0+/, ''); // 去除左侧的零 return { html: '<span class="fc-day-number">' + info.dayNumberText + '</span>' }; }, dayCellDidMount: function (info) { var el = info.el; var num = el.querySelector('.fc-day-number'); if (num) { num.style.color = '#000'; // 将日期数字颜色改为黑色 } el.style.backgroundColor = '#fff'; // 将日期单元格背景改为白色 }, dayHeaderContent: function (info) { return { html: "<span style='color: black'>" + info.text + "</span>" }; }, }); calendar.render(); fechaCita.addEventListener("click", function () { var modalEl = document.getElementById('calendarioModal'); var modal = new bootstrap.Modal(modalEl); modal.show(); });
HTML代码
<div class="modal fade" tabindex="-1" id="calendarioModal" aria-labelledby="modal-fecha-label" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-body"> <button type="button" class="close" data-dismiss="modal">×</button> <br> <div id="calendario"></div> </div> </div> </div> </div>
问题原因
核心问题是FullCalendar在模态框处于隐藏状态(display: none)时完成了初始化渲染。此时日历的DOM元素没有实际尺寸,FullCalendar无法正确绑定日期单元格的点击事件,也无法计算交互区域的位置。只有当点击月份切换按钮触发日历重新渲染时,DOM已经处于可见状态,交互逻辑才会正常工作。
解决办法
方法一:模态框显示后再初始化/渲染日历
将日历的初始化或渲染逻辑移到Bootstrap模态框的shown.bs.modal事件回调中,确保模态框完全显示后再处理日历:
var calendar = null; var modalEl = document.getElementById('calendarioModal'); // 绑定模态框显示完成事件 modalEl.addEventListener('shown.bs.modal', function() { if (!calendar) { // 首次显示时初始化日历 var calendarEl = document.getElementById('calendario'); calendar = new FullCalendar.Calendar(calendarEl, { showNonCurrentDates: true, locale: 'es', selectable: true, editable: true, eventColor: 'red', eventTextColor: '#fff', height: 'auto', buttonText: { today: 'Hoy', }, eventOverlap: false, dateClick: function (info) { var fechaSeleccionada = info.dateStr; document.getElementById("fechaCita").value = fechaSeleccionada; }, dayCellContent: function (info) { info.dayNumberText = info.dayNumberText.replace(/^0+/, ''); return { html: '<span class="fc-day-number">' + info.dayNumberText + '</span>' }; }, dayCellDidMount: function (info) { var el = info.el; var num = el.querySelector('.fc-day-number'); if (num) { num.style.color = '#000'; } el.style.backgroundColor = '#fff'; }, dayHeaderContent: function (info) { return { html: "<span style='color: black'>" + info.text + "</span>" }; }, }); } // 强制渲染日历 calendar.render(); }, { once: true }); // 确保事件只绑定一次 fechaCita.addEventListener("click", function () { var modal = new bootstrap.Modal(modalEl); modal.show(); });
方法二:模态框显示后强制重新渲染日历
如果不想调整初始化时机,直接在模态框显示后调用calendar.render()刷新日历:
fechaCita.addEventListener("click", function () { var modalEl = document.getElementById('calendarioModal'); var modal = new bootstrap.Modal(modalEl); // 模态框显示完成后重新渲染日历 modalEl.addEventListener('shown.bs.modal', function() { calendar.render(); }); modal.show(); });
注意事项
- 避免重复绑定事件:使用
{ once: true }选项或全局绑定事件,防止每次点击输入框都添加新的事件监听。 - 不要提前渲染日历:移除原代码中提前执行的
calendar.render(),确保日历在模态框可见后才完成渲染。
内容的提问来源于stack exchange,提问作者Martín Yanes
相关产品推荐
相关产品推荐

