2
votes

Fullcalendar version is 3.9.0.

When I double click button 'Prev' or 'Next' on top left corner, the view will go backward or forward two months. That's fine. But the events in the view retrieved through Promise are duplicate in this case. They are even trippled following quick clicks. Duplicate events showed in Month view

I tried to use 'event.stopPropagation();' to stop event bubbling but no luck. After transformed event dblclick event into single click, Fullcalendar seemed did not respond accordingly. It may skip into next year or previous year if double click is triggered. It still skip months and showed duplicate events.

$("button[aria-label='prev']").on('dblclick', function(e) {
    e.stopPropagation();
});

For retrieving events in Fullcalendar, please find the code as following.

$('#calendar').fullCalendar({ 
    theme: true,
        header: {
        left: 'prev,next today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay,listMonth,listYear'
        },
    viewRender : function(view, element) {     
        viewRenderInit(view, element);
    },
    ... 
});

//when switch/init view, only get events related to current calendar view

let viewRenderInit = function (view, element) {

    $('#calendar').fullCalendar( 'removeEvents');

    let u = '/getbookings';
    let r = '';
    let _common_params = '_token='+$("[name=\'_token\']").val()+'&view='+view.name+'&time_frame='+ view.title;

    get(u, _common_params).then(function(response) {
        r = response;
        $('#calendar').fullCalendar( 'addEventSource', JSON.parse(r));
    }, function(error) {
        console.error("Failed!", error);
    });
}


let get = function(url, params) {
    return new Promise(function(resolve, reject) {    
        var req = new XMLHttpRequest();
        req.open('GET', url+"?"+params, true);

        req.onload = function() {      
            if (req.status == 200) {       
                resolve(req.response);
            }
            else {        
                reject(Error(req.statusText));
            }
        };

        req.onerror = function() {
            reject(Error("Network Error"));
        };

        req.send();
    });
}

I expect disable event dblclick for button 'Prev' or 'Next'. Alternately, disalbe retrieving duplicate events through Promise via Ajax call .

Appreciate for any suggestion.

2
How are you adding the events to the calendar? Please show that. Otherwise we cannot know how they come to be duplicated. If you add your events in the recommended way as per the documentation then this type of issue should not occurADyson
Hi ADyson, thanks for the reply. I just added the code for retrieving events in this question.Robert Liu

2 Answers

1
votes

Ok, your method is not the recommended way to add events in fullCalendar. The documentation mentions three suitable ways (see https://fullcalendar.io/docs/v3/event-data). For your case I would think the "events as JSON feed" approach would be suitable, and save you quite a bit of code. See https://fullcalendar.io/docs/v3/events-json-feed for details.

The idea of this approach is that fullCalendar handles all the details of sending an AJAX request on your behalf. It will

a) send a new request every time the calendar moves to a new date range

b) send a start and end date automatically in the request so that your server can return a suitable set of events to be displayed (i.e. events which fall within those dates). (Right now, your code does not send dates, so I assume your server must just be returning dates for all time, which, after you've been using your application for a while might end up being a very big list, most of which no-one will look at.)

c) still allow you to add extra info to the request such as your security token

It's really simply to set up:

$('#calendar').fullCalendar({ 
    theme: true,
    header: {
        left: 'prev,next today',
        center: 'title',
        right: 'month,agendaWeek,agendaDay,listMonth,listYear'
    },
    events: {
      url: "/getbookings",
      data: {
        _token: $("[name='_token']").val()
      }
    }
});

And that's all you need...no extra viewRender code, and no need for XHR or Promises. fullCalendar will do the rest.


N.B. In your original code you seem to be downloading different events based on the type of view. I can't quite see the logic of this, since views are just different ways of looking at the same time period. If an event occurs on a particular date, then surely you would want to see it on that date, no matter what type of view is being used? It's just a matter of layout, not data.

But if you really do need that for some reason, despite also receiving relevant start/end dates automatically, you can still send that extra data to the server, you can do it (as per the docs) using the dynamic data callback:

events: {
  url: "/getbookings",
  data: function() { // a function that returns an object
    var view = $('#calendar').fullCalendar('getView');
    return {
      _token: $("[name='_token']").val(),
      view: view.name,
      time_frame: view.title
    };
}
}

You'd also need to switch off lazy fetching to make it talk to the server every time the view switches (otherwise it'll only send a request when the date range changes, so switching from month to week inside the same month wouldn't normally cause a new request):

lazyFetching: false
0
votes

You may consider simply turning off the event handler and then rebinding it after a second or two.

$("button[aria-label='prev']").on('click', function(e) {
    $("button[aria-label='prev']").off();
    //the rest of your function here
    setTimeout(function() {
      //rebind the original function
      $("button[aria-label='prev']").on('click', yourOriginalFunction);
    }, 3000);
});