Javascript – fullCalendarjs method fullCalendar(‘clientEvents’) returns duplicate events

calendarfullcalendarjavascriptjquery

I am using fullcalendar.io

I dynamically populate my calendar, by adding events via evenSources. Such as:

$('.add-more-events').on('click', function(){
    var myEventSourceUrl = // ... get the event source url somehow
    var eventSourceColor = // ... get the color for this source
    var eventSource = {
        type: 'GET',
        url: myEventSourceUrl,
        color: eventSourceColor
    };
    $('.my-calendar').fullCalendar('addEventSource', eventSource);
}

Likewise, I dynamically unpopulate my calendar, by removing events via eventSource. Such as:

$('.remove-some-events').on('click', function(){
    var myEventSourceUrl = // ... get the event source url somehow
    var eventSourceColor = // ... get the color for this source
    var eventSource = {
        type: 'GET',
        url: myEventSourceUrl,
        color: eventSourceColor
    };
    $('.my-calendar').fullCalendar('removeEventSource', eventSource);
}

So far, so good: visually, events are appearing in the calendar (populated), & disappearing in the calendar (unpopulated) as expected. That is, whenever I click on the relevant button.


At some point, I want to reinitialize my calendar & redisplay the events that were last present in my calendar (keep the last eventSources I suppose).

Pseudo code would look like:

1. Back up my events
2. Destroy my calendar
3. Create & initialize new calendar
4. Add the backed up events (see step 1) to the new calendar

So I implemented the above such as:

var clientEvents = $('.my-calendar').fullCalendar('clientEvents'); /* [1] */
$('.my-calendar').fullCalendar('destroy'); /* [2] */
$('.my-calendar').fullCalendar(calendarOptions); /* [3] */
var arrayLengthClientEvents = clientEvents.length;
for (var i = 0; i < arrayLengthClientEvents; i++) {
    $('.my-calendar').fullCalendar( 'addEventSource', clientEvents[i].source);  /* [4] */
}

But for some reason, I get duplicated events when calling $('.my-calendar').fullCalendar('clientEvents').

Note: it seems to be happening when switching weeks, not sure about this though, it may be unrelated.


Resources:

Best Answer

clientEvents

Retrieves events that FullCalendar has in memory.
.fullCalendar( 'clientEvents' [, idOrFilter ] ) -> Array

So it returns an array of events.

You store it, recreate the FC and then add the source of each event. But the sources are URLs and the same for many events, so you get duplicates.

Basically you are doing

$('.my-calendar').fullCalendar('addEventSource', {url:"/myfeed"});
$('.my-calendar').fullCalendar('addEventSource', {url:"/myfeed"});

which will give you duplicates.

So to fix it, you could check for duplicates and not add them. Add the method below:

var filterOutDuplicateEventSources = function(allEventSources){
    var hash = {};
    var remainingEventSources = [];
    var arrayLength = allEventSources.length;
    for (var i = 0; arrayLength !== 0 && i < arrayLength; i++) {
        var currentEventSource = allEventSources[i];
        var currentEventSourceUrl = currentEventSource.url;
        if(currentEventSourceUrl){
            if(hash[currentEventSourceUrl] === 1){
                continue; //skip this event source, we've already added it
            }else{
                hash[currentEventSourceUrl] = 1; // remember that we add this currentEventSourceUrl
                remainingEventSources.push(currentEventSource);
            }
        }else{
            //handle non-url event sources
        }
    }
    return remainingEventSources;
}

Use this method such as:

// Get all event sources
var allEventSources = [];
var arrayLengthClientEvents = clientEvents.length;
for (var i = 0; i < arrayLengthClientEvents; i++) {
    allEventSources.push( clientEvents[i].source );
}

// Filter out duplicated event sources
var remainingEventSources = filterOutDuplicateEventSources( allEventSources );

Alternatively

Technically, I don't believe that clientEvents is meant to be used that way. What you really need is an eventSources method. But it doesn't exist (might be a good feature request).

I would likely try to store the calendar's event source state outside of fullcalendar. You said you have buttons that turn things on and off, are these basically toggles? Is it possible to determine the state by simply querying your various controls? Something along those lines might be a better solution. Maybe.

Related Topic