@model IEnumerable<DevExtreme.MVC.Demos.Models.DisableDatesAppointment>
@(Html.DevExtreme().Scheduler()
.ID("scheduler")
.DataSource(Model)
.TextExpr("Text")
.StartDateExpr("StartDate")
.EndDateExpr("EndDate")
.Views(new[] { SchedulerViewType.WorkWeek, SchedulerViewType.Month })
.CurrentView(SchedulerViewType.WorkWeek)
.CurrentDate(new DateTime(2021, 5, 25))
.FirstDayOfWeek(FirstDayOfWeek.Sunday)
.StartDayHour(9)
.EndDayHour(19)
.ShowAllDayPanel(false)
.Height(600)
.DataCellTemplate(new JS("dataCellTemplate"))
.DateCellTemplate(new JS("dateCellTemplate"))
.TimeCellTemplate(new JS("timeCellTemplate"))
.OnAppointmentFormOpening("function(e) { onAppointmentFormOpening(e); }")
.OnAppointmentAdding("function(e) { onAppointmentAdding(e); }")
.OnAppointmentUpdating("function(e) { onAppointmentUpdating(e); }")
)
<script>
var dinnerTime = { from: 12, to: 13 };
var holidays = [
new Date(2021, 4, 27),
new Date(2021, 6, 4)
];
function dataCellTemplate(itemData, itemIndex, itemElement) {
var date = itemData.startDate;
var isDisabled = isHoliday(date) || isWeekend(date);
var element = $(`<div>${itemData.text}</div>`);
if (isDisabled) {
element.addClass('disable-date');
} else if (isDinner(date)) {
element.addClass('dinner');
}
return itemElement.append(element);
}
function dateCellTemplate(itemData, itemIndex, itemElement) {
var element = $(`<div>${itemData.text}</div>`);
if (isWeekend(itemData.date)) {
element.addClass('disable-date');
}
return itemElement.append(element);
}
function timeCellTemplate(itemData, itemIndex, itemElement) {
var element = $(`<div>${itemData.text}</div>`);
var date = itemData.date;
if (isDinner(date)) {
element.addClass('dinner');
}
if (hasCoffeeCupIcon(date)) {
element.append('<div class="cafe" />');
}
return itemElement.append(element);
}
function onAppointmentFormOpening(e) {
var startDate = new Date(e.appointmentData.StartDate);
if(!isValidAppointmentDate(startDate)) {
e.cancel = true;
notifyDisableDate();
}
applyDisableDatesToDateEditors(e.form);
}
function onAppointmentAdding(e) {
if(!isValidAppointment(e.component, e.appointmentData)) {
e.cancel = true;
notifyDisableDate();
}
}
function onAppointmentUpdating(e) {
if(!isValidAppointment(e.component, e.newData)) {
e.cancel = true;
notifyDisableDate();
}
}
function notifyDisableDate() {
DevExpress.ui.notify("This date is disabled", "warning", 500);
}
function isValidAppointment(component, appointmentData) {
var startDate = new Date(appointmentData.StartDate);
var endDate = new Date(appointmentData.EndDate);
var cellDuration = component.option('cellDuration');
return isValidAppointmentInterval(startDate, endDate, cellDuration);
}
function isValidAppointmentInterval(startDate, endDate, cellDuration) {
var edgeEndDate = new Date(endDate.getTime() - 1);
if (!isValidAppointmentDate(edgeEndDate)) {
return false;
}
var durationInMs = cellDuration * 60 * 1000;
var date = startDate;
while (date <= endDate) {
if (!isValidAppointmentDate(date)) {
return false;
}
var newDateTime = date.getTime() + durationInMs - 1;
date.setTime(newDateTime);
}
return true;
}
function isValidAppointmentDate(date) {
return !isHoliday(date) && !isDinner(date) && !isWeekend(date);
}
function isHoliday(date) {
var localeDate = date.toLocaleDateString();
return holidays.filter(function(holiday) {
return holiday.toLocaleDateString() === localeDate;
}).length > 0;
}
function isWeekend(date) {
var day = date.getDay();
return day === 0 || day === 6;
}
function isDinner(date) {
var hours = date.getHours();
return hours >= dinnerTime.from && hours < dinnerTime.to;
}
function hasCoffeeCupIcon(date) {
var hours = date.getHours();
var minutes = date.getMinutes();
return hours === dinnerTime.from && minutes === 0;
}
function applyDisableDatesToDateEditors(form) {
var startDateEditor = form.getEditor('StartDate');
startDateEditor.option('disabledDates', holidays);
var endDateEditor = form.getEditor('EndDate');
endDateEditor.option('disabledDates', holidays);
}
</script>
using DevExtreme.MVC.Demos.Models.SampleData;
using DevExtreme.MVC.Demos.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace DevExtreme.MVC.Demos.Controllers {
public class SchedulerController : Controller {
public ActionResult CellTemplates() {
return View(SampleData.AppointmentsWorkHours);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.MVC.Demos.Models {
public class Appointment {
public int AppointmentId { get; set; }
public string Text { get; set; }
public string Description { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public bool AllDay { get; set; }
public string RecurrenceRule { get; set; }
public string RecurrenceException { get; set; }
}
public class DisableDatesAppointment {
public int AppointmentId { get; set; }
public string Text { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool AllDay { get; set; }
public string RecurrenceRule { get; set; }
public string RecurrenceException { get; set; }
}
}
using System;
using System.Collections.Generic;
namespace DevExtreme.MVC.Demos.Models.SampleData {
public partial class SampleData {
public static readonly IEnumerable<Appointment> Appointments = new[] {
new Appointment {
AppointmentId = 1,
Text = "Website Re-Design Plan",
StartDate = "2021-05-24T16:30:00.000Z",
EndDate = "2021-05-24T18:30:00.000Z"
},
new Appointment {
AppointmentId = 2,
Text = "Book Flights to San Fran for Sales Trip",
StartDate = "2021-05-24T19:00:00.000Z",
EndDate = "2021-05-24T20:00:00.000Z",
AllDay = true
},
new Appointment {
AppointmentId = 3,
Text = "Install New Router in Dev Room",
StartDate = "2021-05-24T21:30:00.000Z",
EndDate = "2021-05-24T22:30:00.000Z"
},
new Appointment {
AppointmentId = 4,
Text = "Approve Personal Computer Upgrade Plan",
StartDate = "2021-05-25T17:00:00.000Z",
EndDate = "2021-05-25T18:00:00.000Z"
},
new Appointment {
AppointmentId = 5,
Text = "Final Budget Review",
StartDate = "2021-05-25T19:00:00.000Z",
EndDate = "2021-05-25T20:35:00.000Z"
},
new Appointment {
AppointmentId = 6,
Text = "New Brochures",
StartDate = "2021-05-25T21:30:00.000Z",
EndDate = "2021-05-25T22:45:00.000Z"
},
new Appointment {
AppointmentId = 7,
Text = "Install New Database",
StartDate = "2021-05-26T16:45:00.000Z",
EndDate = "2021-05-26T18:15:00.000Z"
},
new Appointment {
AppointmentId = 8,
Text = "Approve New Online Marketing Strategy",
StartDate = "2021-05-26T19:00:00.000Z",
EndDate = "2021-05-26T21:00:00.000Z"
},
new Appointment {
AppointmentId = 9,
Text = "Upgrade Personal Computers",
StartDate = "2021-05-26T22:15:00.000Z",
EndDate = "2021-05-26T23:30:00.000Z"
},
new Appointment {
AppointmentId = 10,
Text = "Customer Workshop",
StartDate = "2021-05-27T18:00:00.000Z",
EndDate = "2021-05-27T19:00:00.000Z",
AllDay = true
},
new Appointment {
AppointmentId = 11,
Text = "Prepare 2021 Marketing Plan",
StartDate = "2021-05-27T18:00:00.000Z",
EndDate = "2021-05-27T20:30:00.000Z"
},
new Appointment {
AppointmentId = 12,
Text = "Brochure Design Review",
StartDate = "2021-05-27T21:00:00.000Z",
EndDate = "2021-05-27T22:30:00.000Z"
},
new Appointment {
AppointmentId = 13,
Text = "Create Icons for Website",
StartDate = "2021-05-28T17:00:00.000Z",
EndDate = "2021-05-28T18:30:00.000Z"
},
new Appointment {
AppointmentId = 14,
Text = "Upgrade Server Hardware",
StartDate = "2021-05-28T21:30:00.000Z",
EndDate = "2021-05-28T23:00:00.000Z"
},
new Appointment {
AppointmentId = 15,
Text = "Submit New Website Design",
StartDate = "2021-05-28T23:30:00.000Z",
EndDate = "2021-05-29T01:00:00.000Z"
},
new Appointment {
AppointmentId = 16,
Text = "Launch New Website",
StartDate = "2021-05-28T19:20:00.000Z",
EndDate = "2021-05-28T21:00:00.000Z"
}
};
}
}
@-moz-document url-prefix() {
.dx-scheduler-work-space-month .dx-scheduler-date-table-cell {
position: relative;
}
.dx-scheduler-work-space-month .dx-scheduler-date-table-cell .disable-date {
position: absolute;
width: 100%;
height: 100%;
}
}
.disable-date,
.dinner {
height: 100%;
}
.disable-date {
background-image: repeating-linear-gradient(135deg, rgba(244, 67, 54, 0.1), rgba(244, 67, 54, 0.1) 4px, transparent 4px, transparent 9px);
color: #9B6467;
}
.dx-scheduler-header-panel-cell .disable-date {
display: flex;
flex-direction: column;
justify-content: center;
}
.dinner {
background: rgba(255, 193, 7, 0.2);
}
.dx-scheduler-time-panel-cell .dinner {
color: rgba(255, 193, 7);
font-weight: 400;
background: transparent;
}
.dx-draggable {
cursor: auto;
}
td.dx-scheduler-time-panel-cell .dinner .cafe {
height: 200%;
width: 100%;
left: 50%;
-webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M20 3H4v10c0 2.21 1.79 4 4 4h6c2.21 0 4-1.79 4-4v-3h2c1.11 0 2-.9 2-2V5c0-1.11-.89-2-2-2zm0 5h-2V5h2v3zM4 19h16v2H4z"/></svg>');
-webkit-mask-repeat: no-repeat;
-webkit-mask-position-y: 50%;
-webkit-mask-position-x: 100%;
margin-top: -4px;
background-color: #ffc107;
}
.dx-scheduler-date-table-cell {
padding: 0;
opacity: 1;
}