如果从datesRender 事件加载数据时FullCalendar 4 仅显示当月错误的事件?

问题描述

在我的带有 FullCalendar v4.3.1 的 Laravel 8 / jQuery 3.5.1 / bootstrap 4.5.3 应用程序中,我只显示当前月份的事件,用户可以通过单击日历的下一个上个月的箭头来选择月份。

我只需要从数据库中检索选定月份的数据。当用户单击下一个上个月的箭头时,我需要运行数据检索方法。我使用datesRender 事件创建它,但是我遇到了在检索数据时再次触发datesRender 的问题,并且我无限地触发了此方法

我愿意:

jQuery(document).ready(function ($) {

    adExpireDateEvenstLoadWithFullCalendar()  // get data from db for selected month
    ...
}) // jQuery(document).ready(function ($) {

function adExpireDateEvenstLoadWithFullCalendar () { // get data from db for selected month
    var dataArray = {
        '_token': '{{ $csrf_token }}','year': select_year,'month': parseInt(select_month) + 1
    }

    var href = "/admin/get_ad_events"
    $.ajax({
        type: "POST",dataType: "json",url: href,data: dataArray,success: function (response) {
            initFullCalendar(response.events,response.calendar_events_default_date);
        },error: function (error) {
            popupErrorMessage(error.responseJSON.message)
        }
    });

} // function adExpireDateEvenstLoadWithFullCalendar () { // get data from db for selected month

function initFullCalendar(eventsList,calendar_events_default_date) { // init FullCalendar with given array of data and month
    if (typeof window.calendarEventsObject != "undefined") { // clear existing instance
        window.calendarEventsObject.destroy();
    }

    var calendarEl = document.getElementById('expire_date_events_calendar');

    var current_date = moment(calendar_events_default_date).format('YYYY-MM-DD')
    var today = moment();

    window.calendarEventsObject = new FullCalendar.Calendar(calendarEl,{ // FullCalendar Init
        plugins: ['dayGrid','timeGrid'],defaultview: 'dayGridMonth',views: {
            dayGridMonth: {
                buttonText: 'Month'
            },timeGridWeek: {
                buttonText: 'Week'
            }
        },axisFormat: "H:mm A",timeFormat: "H:mm A",header: {
            left: 'dayGridMonth,timeGridWeek',center: 'title',right: 'today prev,next '
        },eventRender: function (eventInfo) {
            ...
        },// eventRender: function (eventInfo) {


        dayRender: function (date) {
           ...
        },datesRender: function (view) {
            select_year= view.view.currentStart.getFullYear()
            select_month= view.view.currentStart.getMonth()
            if (calendarExpireDateEventsObject) {
                calendarExpireDateEventsObject.datepicker('setDate',new Date(select_year,select_month,1)).trigger('change');
                adExpireDateEvenstLoadWithFullCalendar() // I need to read data for selected month and THIS RAISE endless triggering of this method

            }
        },// datesRender

        select: function (start,end,allDay) {
            ...
        },events: eventsList,defaultDate: current_date,showNonCurrentDates: false,displayEventTime: true,eventLimit: true,// allow "more" link when too many events

        editable: true,allDaySlot: true,selectable: true,selectHelper: true,selectOverlap: false,fixedWeekCount: false,disableDragging: true,aspectRatio: 0.4,height: 900,eventClick: function (clickObj) {
            ...
            return false;
        },});  // window.calendarEventsObject = new FullCalendar.Calendar(calendarEl,{ // FullCalendar Init
    //    'calendar_events_default_date' => '2019-08-22',window.calendarEventsObject.render(
        {
            backgroundColor: 'green',textColor: 'yellow',}
    );

    jQuery('.eo-fullcalendar').on('click','.fc-event',function (e) {
        e.preventDefault();
        ...
    });

}   // function initFullCalendar(eventsList,calendar_events_default_date) { // init FullCalendar with given array of data and month

任何提示如何修复?

修改块: 我找到了这个 https://fullcalendar.io/docs/v4/events-function 页面 并尝试在我的刀片页面中使用它:

@section('scripts')

<link rel="stylesheet" href="{{ asset('/css/fullcalendar/core/main.css') }}" type="text/css">
<link rel="stylesheet" href="{{ asset('/css/fullcalendar/daygrid/main.css') }}" type="text/css">
<link rel="stylesheet" href="{{ asset('/css/fullcalendar/timegrid/main.css') }}" type="text/css">

<link href="{{ asset('css/gijgo.min.css') }}" rel="stylesheet" type="text/css">
<link href="{{ asset('css/jquery-ui.css') }}" rel="stylesheet" type="text/css">

<script src="{{ asset('js/moment.min.js') }}"></script>
<script src="{{ asset('js/popper.min.js') }}"></script>
<script src="{{ asset('js/bootstrap.min.js') }}"></script>


<script src="{{ asset('js/fullcalendar/core/main.js') }}"></script>
<script src="{{ asset('js/fullcalendar/daygrid/main.js') }}"></script>
<script src="{{ asset('js/fullcalendar/timegrid/main.js') }}"></script>


<script src="{{ url('js/jquery-ui.min.js') }}"></script>

<script>

    let select_year = '{{ $select_year }}'
    let select_month = '{{ $select_month }}'
    let calendarExpireDateEventsObject = null
    
    jQuery(document).ready(function ($) {
        backendInit('list','expire_date_events_calendar')
        // fullCalendarInit()
        console.log('BEFORE::')
        // import { req } from 'superagent'; // ajax library

        var calendar = new Calendar(calendarEl,{

            events: function(info,successCallback,failureCallback) {

                req.get('myxmlFeed.PHP')
                    .type('xml')
                    .query({
                        start: info.start.valueOf(),end: info.end.valueOf()
                    })
                    .end(function(err,res) {

                        if (err) {
                            failureCallback(err);
                        } else {

                            successCallback(
                                Array.prototype.slice.call( // convert to array
                                    res.getElementsByTagName('event')
                                ).map(function(eventEl) {
                                    return {
                                        title: eventEl.getAttribute('title'),start: eventEl.getAttribute('start')
                                    }
                                })
                            )
                        }
                    })

            }

        });

我在控制台中出错:

jquery.min.js:2 Uncaught ReferenceError: Calendar is not defined
    at HTMLDocument.<anonymous> 

也许我错过了一些 .js 文件? 包含的文件列表对我的priorcode工作正常...... 所有文件 v4.3.0。

谢谢!

解决方法

你说

我需要在用户点击 Next Prior 时运行数据检索方法 月份箭头

...但实际上不,你没有。您需要遵循 fullCalendar 提供的正确系统来执行此操作。见https://fullcalendar.io/docs/v4/events-function。如果你给 fullCalendar 一个运行你的 AJAX 请求的回调函数,它会在需要新事件时自动调用该函数(即当显示的日期范围发生变化时)。它将当前开始/结束日期传递给函数,以便您可以在 AJAX 中使用它们发送到服务器。无需弄乱日期渲染等

您似乎在将文档与您自己的代码相关联时遇到了一些问题,因此这里是您应该如何操作的示例。显然我没有测试过这个,但这应该给你正确的想法。

此外,目前您正在向服务器发送月份和年份,但 fullCalendar 会向您传递特定的开始和结束日期。您应该将这些发送到您的服务器。然后您应该修改服务器代码,使其返回这些开始和结束日期内的所有事件,而不是特定月份的事件。这是因为,例如,如果您使用“周”视图而不是“月”视图,fullCalendar 发送的日期将涵盖 1 周而不是 1 个月。因此,您需要更多的灵活性,而不仅仅是返回整月的事件。

jQuery(document).ready(function ($) {
    loadCalendar();  //initialise the calendar
})

function loadCalendar() {

    var calendarEl = document.getElementById('expire_date_events_calendar');
    window.calendarEventsObject = new FullCalendar.Calendar(calendarEl,{ // FullCalendar Init
        plugins: ['dayGrid','timeGrid'],defaultView: 'dayGridMonth',views: {
            dayGridMonth: {
                buttonText: 'Month'
            },timeGridWeek: {
                buttonText: 'Week'
            }
        },axisFormat: "H:mm A",timeFormat: "H:mm A",header: {
            left: 'dayGridMonth,timeGridWeek',center: 'title',right: 'today prev,next '
        },eventRender: function (info) {
            //...
        },dayRender: function (dayRenderInfo) {
           //...
        },select: function (selectionInfo) {
            //...
        },events: function(info,successCallback,failureCallback) {    //get data from db for selected dates
          var dataArray = {
            '_token': '{{ $csrf_token }}','start': info.startStr,'end': info.endStr
          }
          var href = "/admin/get_ad_events";
    
          $.ajax({
              type: "POST",dataType: "json",url: href,data: dataArray,success: function (response) {
                  successCallback(response.events);
              },error: function (error) {
                  failureCallback(error);
                  popupErrorMessage(error.responseJSON.message);
              }
          });
        },showNonCurrentDates: false,displayEventTime: true,eventLimit: true,// allow "more" link when too many events
        editable: true,allDaySlot: true,selectable: true,selectHelper: true,selectOverlap: false,fixedWeekCount: false,disableDragging: true,aspectRatio: 0.4,height: 900,eventClick: function (eventClickInfo) {
            //...
            return false;
        }
    });
}