Articles in this section
Category / Section

How to limit the appointment per slot in ASP.Net Core Scheduler ?

3 mins read

This knowledge base article explains the way to prevent the rendering of more appointments in same range.

 

Step 1: Create a Core sample with by referring the following user guide sample link.

https://help.syncfusion.com/aspnet-core/schedule/getting-started

Also define the Scheduler with before-appointment-create, before-appointment-change, drag-stop and resize-stop client-side events as shown in the following code example.

<ej-schedule id="Schedule1" width="100%" height="525px" current-date="new DateTime(2016, 6, 2)" before-appointment-create="limitAppCount" before-appointment-change="limitAppCount" drag-stop="limitAppCount" resize-stop="limitAppCount">
    <e-appointment-settings apply-time-offset="false" id="Id" subject='"Subject"' start-time='"StartTime"' end-time='"EndTime"' all-day='"AllDay"' recurrence='"Recurrence"' recurrence-rule='"RecurrenceRule"'>
        <e-datamanager id="Data" json="(IEnumerable<SyncfusionASPNETCoreApplication3.Controllers.HomeController.ScheduleData>)ViewBag.datasource"></e-datamanager>
    </e-appointment-settings>
</ej-schedule>

 

Step 2: When any CRUD action is performed on an appointment, Scheduler events will raise where we can access the updated collection details which is passed to the overlap client-side function to check any other appointment availability on rendering range as shown in the following code example.

function limitAppCount(args) {
    if (args.type != 'beforeAppointmentRemove') {
        if (ej.isNullOrUndefined(args.appointment[0]))
            app = args.appointment;
        else
            app = args.appointment[0];
        if (args.type == 'beforeAppointmentCreate' && args.appointment.length > 0) {
            var count = 0;
            for (var i = 0; i < args.appointment.length; i++) {
                app = args.appointment[i];
                count += overlap(app, args.type);
            }
        }
        else if (args.type == "beforeAppointmentChange") {
            var count = 0;
            if (args.appointment.added.length > 0) {
                for (var i = 0; i < args.appointment.added.length; i++) {
                    app = args.appointment.added[i];
                    count += overlap(app, args.type);
                }
            }
            app = args.appointment.changed[0];
            count += overlap(app, args.type);
        } else {
            var count = overlap(app, args.type);
        }
        if (args.type != "resizeStop" && args.type != "dragStop") {
            args.cancel = (count > 0);
        } else {
            args.cancel = (count > 1);
        }
    }
}

 

Step 3: In overlap function, the presence of existing appointment within the new appointment’s rendering range will be calculated with in filterAppointment and recOverlap functions for non-recurrence and recurrence appointments respectively as shown in the following code example.

function overlap(app, type) {
    var obj = $("#Schedule1").ejSchedule('instance');
    var filterApp;
    var filApp = [];
    var startDate = app[obj._appointmentSettings["startTime"]];
    var endDate = app[obj._appointmentSettings["endTime"]];
    var resourceId = app["OwnerId"];
    if (ej.isNullOrUndefined(app[obj._appointmentSettings["recurrenceRule"]])) {
        filterApp = filterAppointment(startDate, endDate);
    }
    else {
        filterApp = recOverlap(app);
    }
    if ((type == "beforeAppointmentChange")) {
        for (var i = 0; i < filterApp.length; i++) {
            if (filterApp[i].AppTaskId != app.AppTaskId) {
                filApp.push(filterApp[i]);
            }
        }
        filterApp = [];
 
        for (var i = 0; i < filApp.length; i++) {
            filterApp.push(filApp[i]);
        }
    }
    var overlapCount = 0;
    if (obj._tempResource.length > 0) {
        overlapCount = (type == "beforeAppointmentChange" && filterResApp.length == 1 && filterResApp[0].Id == app.Id) ? 0 : filterResApp.length;
    }
    else {
        overlapCount = filterApp.length;
    }
    return overlapCount;
}

 

Step 4: In filterAppointment function, start and end time is used to find the overlapping appointment as shown in the following code example.

function filterAppointment(startDate, endDate) {
    var obj = $("#Schedule1").ejSchedule('instance');
    var predicate = ej.Predicate(obj._appointmentSettings["startTime"], ej.FilterOperators.greaterThanOrEqual, startDate).
        and(ej.Predicate(obj._appointmentSettings["endTime"], ej.FilterOperators.greaterThanOrEqual, startDate)).
        and(ej.Predicate(obj._appointmentSettings["startTime"], ej.FilterOperators.lessThan, endDate)).
        or(ej.Predicate(obj._appointmentSettings["startTime"], ej.FilterOperators.lessThanOrEqual, startDate).
            and(ej.Predicate(obj._appointmentSettings["endTime"], ej.FilterOperators.greaterThan, startDate)));
    var filterApp = new ej.DataManager(obj._processed).executeLocal(new ej.Query().where(predicate));
    return filterApp;
}

 

Step 5: In recOverlap function, appointment occurrence objects are formed manually based on its rule. With those occurrence objects, overlapping appointment is found as shown in the following code example.

function recOverlap(app) {
    var appointment = app;
    var obj = $("#Schedule1").ejSchedule('instance');
    var recurEdit = obj._recurrenceEditor.ejRecurrenceEditor('instance');
    recurEdit._rRule = {};
    recurEdit.model.startDate = new Date(obj.currentDate());
    var rule = app[obj._appointmentSettings["recurrenceRule"]];
    var collection = recurEdit.recurrenceDateGenerator(appointment[obj._appointmentSettings["recurrenceRule"]], appointment[obj._appointmentSettings["startTime"]], appointment[obj._appointmentSettings["recurrenceExDate"]]);
    var newArray = collection;
    var filter = [];
    var i = 0;
    while (i < newArray.length) {
        var orgStrTime = new Date(newArray[i]), orgEndTime = appointment[obj._appointmentSettings["endTime"]];
        ((recurEdit._rRule.freq == "MONTHLY" || recurEdit._rRule.freq == "YEARLY") && !ej.isNullOrUndefined(recurEdit._rRule.setPositions)) && (orgStrTime = recurEdit._dayOfWeekInMonth(orgStrTime, recurEdit._rRule.weekDays, recurEdit._rRule.setPositions));
        var strTime = new Date(orgStrTime.getFullYear(), orgStrTime.getMonth(), orgStrTime.getDate(), new Date(appointment[obj._appointmentSettings["startTime"]]).getHours(), new Date(appointment[obj._appointmentSettings["startTime"]]).getMinutes(), new Date(appointment[obj._appointmentSettings["startTime"]]).getSeconds());
        var endTime = new Date(new Date(strTime).setMilliseconds(appointment[obj._appointmentSettings["endTime"]].getTime() - appointment[obj._appointmentSettings["startTime"]].getTime()));
        var fil = filterAppointment(strTime, endTime);
        if (typeof fil !== 'undefined' && fil.length > 0) {
            for (var j = 0; j < fil.length; j++) {
                filter.push(fil[j]);
                // To add exclude date
                app[obj._appointmentSettings["recurrenceRule"]] = ej.isNullOrUndefined(app[obj._appointmentSettings["recurrenceExDate"]]) ? rule + ";EXDATE=" + ej.format(strTime, obj._pattern.d, obj.model.locale) : app[obj._appointmentSettings["recurrenceRule"]] + "," + ej.format(strTime, obj._pattern.d, obj.model.locale);
                app[obj._appointmentSettings["recurrenceExDate"]] = !ej.isNullOrUndefined(app[obj._appointmentSettings["recurrenceExDate"]]) ? app[obj._appointmentSettings["recurrenceExDate"]] + "," + ej.format(strTime, obj._pattern.d, obj.model.locale).toString() : ej.format(strTime, obj._pattern.d, obj.model.locale).toString();
            }
        }
        i++;
    }
    return filter;
}

 

Step 6: Run the sample and no two appointments can be rendered in the same time range as shown below.

Appointment range screenshot in ASP.NET Core

    Figure 1: Adding second appointment in another appointment range.

 

Appointment range screenshot in ASP.NET Core

Figure 2: Second appointment is not rendered, due to the presence of another appointment in same range.

 

Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/Sample727027404

 

Did you find this information helpful?
Yes
No
Help us improve this page
Please provide feedback or comments
Comments (0)
Please  to leave a comment
Access denied
Access denied