FullCalendar批量选日期时模态框Delete按钮首次不显示求助
问题:FullCalendar批量选择日期时首次弹出模态框不显示Delete按钮
我用fullcalendar.io开发日历功能,结合jQuery、Flask与MySQL实现事件存储。需求是:批量选择日历日期时弹出模态框,选中日期无事件时只显示Add按钮;有事件时同时显示Delete按钮支持批量删除。但现在遇到问题:首次批量选择时,不管日期有没有事件,Delete按钮都不显示,关闭模态框后再次操作功能正常,找不到原因,求解决办法。
现有代码
JavaScript代码
$(document).ready(function() { $('#calendar').fullCalendar({ selectable: true, firstDay : 1, editable : true, select: function(start, end, jsEvent, view) { // 获取选中的开始和结束日期 var startDate = start.format('YYYY-MM-DD'); var endDate = end.subtract(1, 'days').format('YYYY-MM-DD'); var selectedDays = []; var currentDate = start; while(currentDate <= end){ selectedDays.push(currentDate.format('YYYY-MM-DD')); currentDate.add(1, 'day') } if (startDate === endDate) { $('#addEventModal').modal('show'); $('#addEventForm input[name="days"]').val(startDate); } else { $('#addEventModal').modal('show'); $('#addEventForm input[name="days"]').val(selectedDays.join(', ')); } }, height : 600, defaultView : 'month', events: '/manager/get_events', }); }); $('#addEventModal').on('show.bs.modal', function() { var selectedDays = $('#addEventForm input[name="days"]').val().split(', '); var eventsExist = false; for (var i = 0; i < selectedDays.length; i++) { var events = $('#calendar').fullCalendar('clientEvents', function(event) { return event.start.format('YYYY-MM-DD') === selectedDays[i]; }); if (events.length > 0) { eventsExist = true; break; } } if (eventsExist) { $('#deleteEventsBtn').show(); } else { $('#deleteEventsBtn').hide(); } }); $('#deleteEventsBtn').click(function(){ var selectedDays = $('#addEventForm input[name = "days"]').val().split(', ') deleteEventsByDay(selectedDays); }); function deleteEventsByDay(selectedDays) { for (var i = 0; i < selectedDays.length; i++) { var events = $('#calendar').fullCalendar('clientEvents', function(event) { return event.start.format('YYYY-MM-DD') === selectedDays[i]; }); for (var j = 0; j < events.length; j++) { deleteEvent(events[j].id); } $('#calendar').fullCalendar('removeEvents', function(event) { return event.start.format('YYYY-MM-DD') === selectedDays[i]; }); } }
HTML模态框代码
<div id="addEventModal" class="modal fade" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h4 class="modal-title text-primary" style="align-content: center;">Add Event</h4> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form id="addEventForm" action="{{url_for('Manager_crud_hours.add_bulk_events')}}" method="POST"> <div class="form-group"> <label for="project_id">Project:</label> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-tasks"></i></span> <select class="form-control" id="project_id" name="project_id"> {% for row in projects %} <option value="{{row.project_id}}">{{row.project_name}}</option> {%endfor%} </select> </div> </div> <div class="form-group"> <label>Worked Hours:</label> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-time"></i></span> <input type="number" class="form-control" name="time" placeholder="Enter Worked Hours"> </div> </div> <div class="form-group"> <label>Worked Day:</label> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span> <input type="text" class="form-control" name="days" id="addEventDay" placeholder="Select Worked Day" readonly> </div> </div> <div class = "modal-footer"> <button class="btns btns-primary" type="submit">Add</button> <button class="btns btns-danger" id="deleteEventsBtn" style = "display: none;">Delete</button> </div> </form> </div> </div> </div> </div>
问题原因与解决方案
原因分析
- 赋值与模态框显示顺序颠倒:首次操作时先触发
modal('show'),再给days输入框赋值,导致show.bs.modal事件执行时,输入框还是空值,检测不到已有事件,Delete按钮保持隐藏。 - 闭包陷阱:循环中
selectedDays[i]在clientEvents回调执行时已变成循环结束后的最终值,导致日期匹配错误,无法正确检测事件。
修复步骤
1. 调整赋值与模态框显示顺序
先给输入框赋值,再显示模态框,确保show.bs.modal事件能拿到正确的选中日期:
select: function(start, end, jsEvent, view) { var startDate = start.format('YYYY-MM-DD'); var endDate = end.subtract(1, 'days').format('YYYY-MM-DD'); var selectedDays = []; var currentDate = start.clone(); // 克隆对象避免修改原start实例 while(currentDate.isSameOrBefore(end)){ // 用fullCalendar内置方法判断日期更可靠 selectedDays.push(currentDate.format('YYYY-MM-DD')); currentDate.add(1, 'day') } // 先赋值,再显示模态框 if (startDate === endDate) { $('#addEventForm input[name="days"]').val(startDate); $('#addEventModal').modal('show'); } else { $('#addEventForm input[name="days"]').val(selectedDays.join(', ')); $('#addEventModal').modal('show'); } }
2. 解决闭包陷阱
用立即执行函数(IIFE)捕获循环中的当前日期,确保回调能拿到正确值:
$('#addEventModal').on('show.bs.modal', function() { var selectedDays = $('#addEventForm input[name="days"]').val().split(', '); var eventsExist = false; for (var i = 0; i < selectedDays.length; i++) { // IIFE捕获当前循环的日期 (function(day) { var events = $('#calendar').fullCalendar('clientEvents', function(event) { return event.start.format('YYYY-MM-DD') === day; }); if (events.length > 0) { eventsExist = true; } })(selectedDays[i]); if (eventsExist) break; // 检测到事件后直接跳出循环 } $('#deleteEventsBtn').toggle(eventsExist); // 用toggle简化显示/隐藏逻辑 });
3. 同步修复删除函数的闭包问题
确保删除事件时匹配正确日期:
function deleteEventsByDay(selectedDays) { for (var i = 0; i < selectedDays.length; i++) { (function(day) { var events = $('#calendar').fullCalendar('clientEvents', function(event) { return event.start.format('YYYY-MM-DD') === day; }); for (var j = 0; j < events.length; j++) { deleteEvent(events[j].id); } $('#calendar').fullCalendar('removeEvents', function(event) { return event.start.format('YYYY-MM-DD') === day; }); })(selectedDays[i]); } }
验证效果
修改后首次批量选择日期时,模态框会先获取正确的选中日期,再执行事件检测,Delete按钮会根据日期是否有事件正确显示/隐藏,同时避免了闭包导致的日期匹配错误。
内容的提问来源于stack exchange,提问作者Bilge Kaan Özkan
相关产品推荐
相关产品推荐

