3

I have used eventOverlap: false, and selectOverlap: false, to prevent the user from overlapping events. However, I am trying to prevent the user from overlapping existing events.

In my full calendar the user can click on an event, which opens a pop up dialog and allows the user to update the date/time of the selected event. However, the user is able choose a date/time where an event is already booked. Therefore, I want to have a validation on the Save button that checks if the updated date/time has an event or not before any changes are made. These two screen shots show this problem graphically. 1. Shows that event time is being updated. 2. Shows the event is overlapping after it has been updated

var events = []; //global array where all the events are stored

function FetchEventAndRenderCalendar() {
//fetch info from database and add it to the events array
events = [];
$.ajax({
    type: "GET",
    url: "/SessionScheduler/GetEvents",
    success: function (data) {
    $.each(data, function (i, v) {    
         events.push({
             id: v.Id,
             title: v.Title,
             description: v.Description,
             start: moment(v.StartDate),
             end: moment(v.EndDate),
             tutorName: v.TutorName,
             color: v.ThemeColour
            });
      })
     //then display the calendar with the events
      GenerateCalender(events);
   },
   error: function (error) {
       alert('failed');
     }
  })
}

This is the Save button where I want to have a validation check. I have looked at this solution but this didn't work for me

$('#btnSave').click(function () {
                    //validation
                    var selectedStartDate = moment(document.getElementById('txtStart').value.trim(), "DD/MM/YYYY HH:mm a").toDate();
                    var selectedEndDate = moment(document.getElementById('txtEnd').value.trim(), "DD/MM/YYYY HH:mm a").toDate();
                    if (selectedStartDate > selectedEndDate) {
                        alert('Invalid end date');
                        return;
                    }

                    if (selectedStartDate.getTime() == selectedEndDate.getTime()) {
                        alert('Start/End dates can not be the same');
                        return;
                    }

                    var data = {
                        Id: $('#hdEventID').val(),
                        Title: $('#txtTitle').val(),
                        StartDate: $('#txtStart').val(),
                        EndDate: $('#txtEnd').val(),
                        Description: $('#txtDescription').val(),
                        TutorName: $('#txtTutorName').val(),
                        ThemeColour: $('#ddThemeColour').val()
                    }
                    SaveEvent(data);
                })

SaveEvent function: Which saves the data

        function SaveEvent(data) {
            if (selectedEvent != null && confirm("Are you sure?")) {
                $.ajax({
                    type: "POST",
                    url: '/SessionScheduler/SaveEvent',
                    data: data,
                    success: function (data) {
                        if (data.status) {
                            //refresh the calendar if the status is true else its failed
                            FetchEventAndRenderCalendar();
                            $('#myModalSave').modal('hide'); //hide modal dialog pop window
                        }
                    },
                    error: function () {
                        alert('Failed');
                    }
                })
            }
        }
Big Smile
  • 1,103
  • 16
  • 30
  • Hi! Which fullcalendar version do you use? How does your `SaveEvent(data);` function looks like? what does happen if you use [eventOverlap](https://fullcalendar.io/docs/event_ui/eventOverlap/) and or [selectOverlap](https://fullcalendar.io/docs/selection/selectOverlap/)? – LakiGeri Sep 26 '17 at 07:45
  • @LakiGeri I am using this [Full Calendar](https://fullcalendar.io/) the version I am using is **3.4.0.**. And eventOverlap or selectOverlap prevents the user from overlapping events when they drag and drop an event on to another one. I have added the SaveEvent function to the actual question. Thank you – Big Smile Sep 26 '17 at 08:16
  • `eventOverlap` only applies to when you're dragging and dropping, it doesn't work when you have your own custom logic to enter the new dates. Therefore, you need your own custom logic to check for overlaps. You can do it on the client (against the events currently displayed on screen), but if the user can specify a date outside the current fullCalendar view, then you must write the logic for this in your server code, when the ajax request is made. We can't see that code and so can't really help you with it. But probably it can be done via SQL. – ADyson Sep 26 '17 at 08:37
  • I see, and do you have a DB of events on the server side, where you can check the overlapping problem, via an ajax request before the fullcalendar adding method? – LakiGeri Sep 26 '17 at 08:38
  • Since, I have a global array of events which holds all the events. I just want to loop over the events array in the **$('#btnSave').click** function to check for validation. If the date/time that the user chose has an event booked, I just want to display an error message. But I don't know how to do that. – Big Smile Sep 26 '17 at 09:05
  • "I don't know how to do that." Do what? Loop over the array? Do the logic to check for overlap? Display a message? Which bit is the problem? P.S. you should absolutely 100% still do that same overlap-checking process on the server as well, in case another user has entered an event into that time period in between the calendar loading and the current user doing this action, and also because client-side validation is trivial to bypass/disable using the developer tools, so you should always validate _all_ user input on the server-side as a standard practice. – ADyson Sep 26 '17 at 10:58
  • @ADyson I mean I just want to loop over the events array in **$('#btnSave').click** function to check each array element's start and end date/time against the selected event to prevent overlap. If the user choose a time in which an event is already book, I just want to show an error message. – Big Smile Sep 26 '17 at 13:47
  • yes that's exactly what you said before. Doesn't answer my question as to which bit you're stuck with? Have you even tried to write it? A loop isn't that hard, neither is an error message. Is the date comparison part a problem? I can give you a general function which will check that, if you're unsure? – ADyson Sep 26 '17 at 13:49
  • I have added an answer containing a function which you can use to check for overlaps, hope this helps. – ADyson Sep 26 '17 at 13:56

2 Answers2

1

I did some search about this problem.

Everytime, they get all the events from the FC memory, and iterate over them, for searching conflict time.

Unfortunately, there is no simple solution for that.

My suggestions:

  1. You should to make a ajax call before every modification, where your server checks the conflict (if you store the events on the server side)
  2. If your server doesn't store your events, then you have to iterate all the events in the client side, in order to find a conflict.
LakiGeri
  • 2,046
  • 6
  • 30
  • 56
1

This function will check whether the event passed in overlaps with any other events currently displayed on the calendar.

Note this relies on the events having unique id properties, so it doesn't check itself. It also cannot, by its nature, check any events not currently displayed on the calendar, because fullCalendar doesn't return those from its clientEvents method. You should check again on the server-side before accepting the modification into your database.

//check whether or not the calendar event passed in overlaps with an existing event in the current (client-side) calendar data
//the first parameter should be the event which is being tested
//the second parameter should be a jQuery object wrapping the calendar HTML element
function isCalendarEventOverlapping(event) 
{
    var evts = cal.fullCalendar('clientEvents');

    for (i in evts) 
    {
        if (evts[i].id != event.id)
        {
            if (event.start.isBefore(evts[i].end) && event.end.isAfter(evts[i].start))
            {
                return true;
            }
        }
    }
    return false;
}
ADyson
  • 57,178
  • 14
  • 51
  • 63
  • This is what I was looking for but I am getting this error **Uncaught TypeError: Cannot read property 'isBefore' of undefined**. Do you why I might be getting this error? – Big Smile Sep 26 '17 at 14:39
  • It would indicate that the property `event.start` (or even possibly `event` itself) is undefined in your code. Did you pass a valid fullCalendar-style event object into the function, one with a valid start date property called `start`, where `start` is a MomentJS object? If you're just using the same code you use to make an event to send to your SaveEvent method, then it won't be, you'll need to make some amendments to either the structure of that, or to this function in order to accomodate that. – ADyson Sep 26 '17 at 14:57
  • Thank you so much for your help. I tired your code but it didn't work for me. However, I solved the issue by implementing a custom logic which I will share. – Big Smile Sep 28 '17 at 12:19