Overview

  • Block past days in the JavaScript Calendar component using disabled cells feature.

  • Prevent navigation to past weeks using 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

javascript calendar blocking past days date picker

You can block access to past days using the Navigator (date picker) component 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 needed:

onTimeRangeSelect: (args) => {
  if (args.day < DayPilot.Date.today()) {
    args.preventDefault();
    nav.select(lastDate, {dontNotify: true, dontFocus: true});
  }
  else {
    lastDate = args.start;
  }
}

In order to provide a visual hint to the users, we will change the background of the blocked days using onBeforeCellRender event handler:

onBeforeCellRender: function(args) {
  if (args.cell.day < DayPilot.Date.today()) {
    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 Navigator configuration now looks like this:

let lastDate = null;

const nav = new DayPilot.Navigator("nav", {
  selectMode: "week",
  onBeforeCellRender: (args) => {
    if (args.cell.day < DayPilot.Date.today()) {
      args.cell.cssClass = "navigator-disabled-cell";
    }
  },
  onTimeRangeSelect: (args) => {
    if (args.day < DayPilot.Date.today()) {
      args.preventDefault();
      nav.select(lastDate, {dontNotify: true, dontFocus: true});
    }
    else {
      lastDate = args.start;
    }
  },
  onTimeRangeSelected: (args) => {
    dp.startDate = args.start;
    dp.update();
  }
});
nav.init();

Calendar: Blocking Drag and Drop

javascript calendar blocking drag and drop

In the Calendar component, it is possible to disable selected grid cells using onBeforeCellRender event handler. This will will make them inaccessible for all drag and drop operations (event creating, moving and resizing):

const dp = new DayPilot.Calendar("dp", {
  // ...
  onBeforeCellRender: (args) => {
    if (args.cell.start < DayPilot.Date.today()) {
      args.cell.disabled = true;
      args.cell.backColor = "#eee";
    }
  }
});
dp.init();

Full Source Code

<!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;
    }

    .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="nav"></div>
  </div>
  <div class="col-main">
    <div id="dp"></div>
  </div>
</div>

<script>

  let lastDate = null;

  const nav = new DayPilot.Navigator("nav", {
    selectMode: "week",
    onBeforeCellRender: (args) => {
      if (args.cell.day < DayPilot.Date.today()) {
        args.cell.cssClass = "navigator-disabled-cell";
      }
    },
    onTimeRangeSelect: (args) => {
      if (args.day < DayPilot.Date.today()) {
        args.preventDefault();
        nav.select(lastDate, {dontNotify: true, dontFocus: true});
      }
      else {
        lastDate = args.start;
      }
    },
    onTimeRangeSelected: (args) => {
      dp.startDate = args.start;
      dp.update();
    }
  });
  nav.init();

  const dp = new DayPilot.Calendar("dp", {
    viewType: "Week",
    onTimeRangeSelected: async (args) => {
      const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
      dp.clearSelection();
      if (!modal.result) { return; }
      dp.events.add(new DayPilot.Event({
        start: args.start,
        end: args.end,
        id: DayPilot.guid(),
        text: modal.result
      }));
    },
    onBeforeCellRender: (args) => {
      if (args.cell.start < DayPilot.Date.today()) {
        args.cell.disabled = true;
        args.cell.backColor = "#eee";
      }
    }
  });
  dp.events.list = [
    {
      id: "1",
      start: DayPilot.Date.today().addHours(10),
      end: DayPilot.Date.today().addHours(12),
      text: "Event 1"
    }
  ];
  dp.init();
</script>

</body>
</html>