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

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">&times;</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>

问题原因与解决方案

原因分析

  1. 赋值与模态框显示顺序颠倒:首次操作时先触发modal('show'),再给days输入框赋值,导致show.bs.modal事件执行时,输入框还是空值,检测不到已有事件,Delete按钮保持隐藏。
  2. 闭包陷阱:循环中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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:35:54