ui-calendar icon indicating copy to clipboard operation
ui-calendar copied to clipboard

Added event is duplicated on changing months and then going back

Open bjm88 opened this issue 10 years ago • 7 comments

I did a test straight from the demo site... http://angular-ui.github.io/ui-calendar/ If you click add event "Open Sesame" comes as expected real time. I think click next arrow at top right to go forward a month. I think click back and that event is duplicated.

I did a few extra tests adding logging, it looks like like 58~ isArray arraySources.push gets called one too many times..

I noticed if I create $scope.events and just add to it in controller all is good, this is only issue if you add after the initial render. I also tested adding events for current month and future month. For future month I added for the 1st, so I basically am im March and add for March and also for April 1. I see both in the view as it shows future month and they are both added only once as desired. As soon as I click next month, the april 1st guy duplicates.

This is a reallly nice directive in general, this is the only major issue I see, can this get fixed? I tried looking at code to figure it out however its not obvious to me where issue is, I wasn't sure if related to angular's $watch or something or just management of these items and tokens seems overly complex with all the adding and removing, but I assumer perhaps that is b/c of what is required for Full Calendar integration.

bjm88 avatar Mar 26 '14 03:03 bjm88

hello,

Yes It seems this issue keeps coming up. I think the best fix will be to move to the new version of fullcalendar. I will work on the new branch over the weekend and see if it fixes the issue.

joshkurz avatar Mar 26 '14 03:03 joshkurz

Thanks Josh. If someone could at a high level design approach in notes that would be awesome. I am concerned if the full remove and add of events will scale. In the real world people may be adding thousands of events over time. Each small addition or adjustment shouldn't have to resend entire event set. I suspect it should support user of widget optimizing for their needs. For example...

Load current year events at first, in background load previous and next year events. On year change in view do same again.

Please let me know your thoughts on this, thanks.

bjm88 avatar Mar 26 '14 12:03 bjm88

@bjm88 you bring up great points. Especially when it comes to your performance queries. We currently have a PR open atm that should help with performance. https://github.com/angular-ui/ui-calendar/pull/77

The issue about the events duplicating has been fixed, but another issue has been introduced because of it. I'm pretty sure It is a fullcalendar issue, but not ruling uiCalendar out fully yet. I thought that upgrading the new v2 branch would solve both issues mentioned, but i was wrong. It's ok though. v2 will be a great opportunity for this repo to contribute back to the fullcalendar project.

joshkurz avatar Mar 29 '14 06:03 joshkurz

As a workaround:

  1. Use fullCalendar("renderEvent", event) to render the event in the "Add Event" handler callback.
  2. Disable lazyFetching in the EventSource object. If you cannot do this due to perfomance requirements, a fine-grain refetching can be done using the viewRender and viewDestroy callbacks.

ygneo avatar Apr 08 '14 17:04 ygneo

I had the same problem. On the inital view, in this case agendaWeek, it all looked nice and dandy, but when switching view all events were duplicated. I solved it by addingand removing event sources when necessary. In this case I'm using fullcalendar 1.6.7.

The code that rendered duplicate code looked something like this:

// Events sources
$scope.events1 = {editable: false, events: []};
$scope.events2 = {editable: true, events: []};

// ng-model of ui-calendar
$scope.eventSources = [
  $scope.events1,
  $scope.events2
];

// Load data and assign to events1 and events2
$scope.events1.events = response.data;
$scope.events2.events = response.data;

To make it work I changed the code to look like this:

// Events sources
$scope.events1 = {editable: false, events: []};
$scope.events2 = {editable: true, events: []};

// ng-model of ui-calendar
$scope.eventSources = [];

// Load data and assign to events1 and events2
$scope.events1.events = response.data;
$scope.eventSources.push($scope.events1);
$scope.events2.events = response.data;
$scope.eventSources.push($scope.events2);

// When reloading data I remove and then add events again
$scope.eventSources.splice(1,1);
$scope.eventSources.push($scope.events2);

johnparn avatar Dec 12 '14 22:12 johnparn

SOLUTION THAT SHOULD WORK FOR ALL:

test for array length:

$scope.myevents = function(start, end, timezone, callback) {
                if($scope.events.length === 0) {
                    $http.get('/api/v1/resource').then(function(response) {
                        angular.forEach(response.data, function(event,key){
                            for(var i = 0 ; i < event.numberOfBookings; i++)
                            {
                                $scope.events.push(event.booking[i] =
                                    {
                                        _id:                    event.booking[i]._id,
                                        title:                  event.title,
                                        resourceNumber:         event.resourceNumber,
                                        description:            event.description,
                                        start:                  event.booking[i].startDateTime,
                                        end :                   event.booking[i].endDateTime,
                                        numberOfBookingExists:  event.numberOfBookingExists
                                    });
                            }
                        });
                        callback($scope.events);

                    });
                }
                else if($scope.events.length > 0)
                {
                    callback($scope.events);
                }
            };

if length = 0, get the events once. if length > 0, call the callback function with the events data.

no need for lazyFetching here!

hope this helps anyone with this issue!

rostgoat avatar Jan 05 '18 22:01 rostgoat

Hello, I was having the same issue so what I did was create a clean function for calendar and I call that function before $('#calendar').fullCalendar('renderEvents', events, true);, to me this worked and solved the issue but please consider this: #1. I use $('#calendar').fullCalendar('renderEvents', eventsToLoad, true) on the viewRender #2. you need to be sure that all events are included in the eventsToLoad , for me this worked because I get all events from the database, so if the event is not saved yet and you change of view the event is lost #3 for my case I have a few events on the calendar so I don't perceived this action BUT if you have many events this can be slow because we iterate one by one #4 is in testing right now, so if I find some bug I'll write it here

here is the code for the clean function is quite simple: function clean_calendar() { var events = $('#calendar').fullCalendar('clientEvents'); if(events.length > 0) { for(var i in events) { $('#calendar').fullCalendar('removeEvents',events[i].id); } } }

hope this help

ar8 avatar Jul 06 '18 19:07 ar8