Overview
Block drag and drop for past days in the JavaScript Calendar component using the disabled cells feature.
Prevent navigation to the past days in the Navigator (date picker) component.
License
Licensed for testing and evaluation purposes. Please see the license agreement included in the sample project. You can use the source code of the tutorial if you are a licensed user of DayPilot Pro for JavaScript.
Live Demo
Blocking Past Days in the Date Picker
You can block access to the past days in the Navigator component (date picker) by customizing the selection logic in onTimeRangeSelect event handler.
In this example, we check the selected date and reset it to the previous value if it is before the specified date:
onTimeRangeSelect: (args) => {
if (args.day < app.firstAvailableDate) {
args.preventDefault();
datepicker.select(app.lastDate, {dontNotify: true, dontFocus: true});
}
else {
app.lastDate = args.start;
}
},
In order to provide a visual hint to the users, we will change the background of the blocked days using the onBeforeCellRender event handler:
onBeforeCellRender: (args) => {
if (args.cell.day < app.firstAvailableDate) {
args.cell.cssClass = "navigator-disabled-cell";
}
},
The navigator-disabled-cell
CSS class changes the background and cursor styles:
.navigator_default_cell.navigator-disabled-cell {
background-color: #ddd !important;
color: #888;
cursor: not-allowed !important;
}
Our date picker configuration now looks like this:
const app = {
lastDate: null,
firstAvailableDate: DayPilot.Date.today().firstDayOfWeek().addDays(2),
// ...
};
// ...
const datepicker = new DayPilot.Navigator("datepicker", {
selectMode: "Week",
onBeforeCellRender: (args) => {
if (args.cell.day < app.firstAvailableDate) {
args.cell.cssClass = "navigator-disabled-cell";
}
},
onTimeRangeSelect: (args) => {
if (args.day < app.firstAvailableDate) {
args.preventDefault();
datepicker.select(app.lastDate, {dontNotify: true, dontFocus: true});
}
else {
app.lastDate = args.start;
}
},
onTimeRangeSelected: (args) => {
calendar.startDate = args.start;
calendar.update();
}
});
datepicker.init();
Blocking Drag and Drop for Selected Days in the Calendar
In the Calendar component, it is possible to disable selected grid cells using the onBeforeCellRender event handler.
This will will make the cells inaccessible for all drag and drop operations (event creating, moving and resizing):
const calendar = new DayPilot.Calendar("calendar", {
onBeforeCellRender: (args) => {
if (args.cell.start < app.firstAvailableDate) {
args.cell.disabled = true;
args.cell.backColor = "#eee";
}
},
// ...
});
calendar.init();
Full Source Code
Here is the full source code of our JavaScript example that blocks access to past dates in the date picker and calendar components:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>JavaScript Calendar: Blocking Selected Dates</title>
<style>
.navigator_default_cell.navigator-disabled-cell {
background-color: #ddd !important;
color: #888;
cursor: not-allowed !important;
}
.calendar_default_event,
.calendar_default_event_inner,
.calendar_default_shadow,
.calendar_default_shadow_inner {
border-radius: 15px;
}
body .calendar_default_event_inner {
background: #f0ad4edd;
border: 1px solid #eea236;
color: #fff;
}
.main {
display: flex;
}
.col-left {
padding-right: 10px;
}
.col-main {
flex: 1;
}
</style>
<!-- DayPilot library -->
<script src="js/daypilot/daypilot-all.min.js"></script>
</head>
<body>
<div class="header">
<h1><a href='https://code.daypilot.org/88013/javascript-calendar-blocking-selected-dates'>JavaScript Calendar: Blocking Selected Dates</a></h1>
<div><a href="https://javascript.daypilot.org/">DayPilot for JavaScript</a> - HTML5 Calendar/Scheduling Components for JavaScript/Angular/React/Vue</div>
</div>
<div class="main">
<div class="col-left">
<div id="datepicker"></div>
</div>
<div class="col-main">
<div id="calendar"></div>
</div>
</div>
<script type="module">
const app = {
lastDate: null,
firstAvailableDate: DayPilot.Date.today().firstDayOfWeek().addDays(2),
loadData() {
const events = [
{
id: 1,
start: DayPilot.Date.today().addDays(2).addHours(10),
end: DayPilot.Date.today().addDays(2).addHours(12),
text: "Event 1"
}
];
calendar.update({events});
},
init() {
this.loadData();
}
};
const datepicker = new DayPilot.Navigator("datepicker", {
selectMode: "Week",
onBeforeCellRender: (args) => {
if (args.cell.day < app.firstAvailableDate) {
args.cell.cssClass = "navigator-disabled-cell";
}
},
onTimeRangeSelect: (args) => {
if (args.day < app.firstAvailableDate) {
args.preventDefault();
datepicker.select(app.lastDate, {dontNotify: true, dontFocus: true});
}
else {
app.lastDate = args.start;
}
},
onTimeRangeSelected: (args) => {
calendar.startDate = args.start;
calendar.update();
}
});
datepicker.init();
const calendar = new DayPilot.Calendar("calendar", {
viewType: "Week",
durationBarVisible: false,
onTimeRangeSelected: async (args) => {
const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
calendar.clearSelection();
if (!modal.result) { return; }
calendar.events.add({
start: args.start,
end: args.end,
id: DayPilot.guid(),
text: modal.result
});
},
onBeforeCellRender: (args) => {
if (args.cell.start < app.firstAvailableDate) {
args.cell.disabled = true;
args.cell.backColor = "#eee";
}
}
});
calendar.init();
app.init();
</script>
</body>
</html>