Appointment Scheduling

The scheduler can be set up for scheduling/unscheduling booked appointments. Simply set up a daily schedule view with multiple resources representing dentists or doctors. Next to the calendar you can render a list of unscheduled appointments.

Enabling advanced validation and combining that with the drag & drop between the calendar and external list on a resource to resource basis you got a pretty nice working base for appointment scheduling that can be further customized.

Download and try example

Demo

Loading the live demo

Preview in full screen

Build a appointment scheduler — assign doctors or dentists, drag from an unscheduled queue, and prevent double-booking.

Code

mobiscroll.setOptions({
  locale:  ,
  theme: ' ',
  themeVariant: ' '
});

var externalCont = document.getElementById('md-docs-appointment-cont');
var now = new Date();
var today = new Date(now.setMinutes(59));
var yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);

var myData = [
  {
    id: 'job1',
    start: '2026-10-22T14:00',
    end: '2026-10-22T16:00',
    resource: 1,
    title: 'Myla Bennett',
    job: 'Wisdom tooth removal',
    color: '#334ab9',
  },
  {
    id: 'job2',
    start: '2026-10-22T17:00',
    end: '2026-10-22T18:30',
    resource: 1,
    title: 'Beatrix Foley',
    job: 'Braces',
    color: '#177e70',
  },
  {
    id: 'job3',
    start: '2026-10-22T08:00',
    end: '2026-10-22T09:30',
    resource: 3,
    title: 'Frank Watson',
    job: 'Teeth whitening',
    color: '#d1891f',
  },
  {
    id: 'job4',
    start: '2026-10-22T10:00',
    end: '2026-10-22T12:30',
    resource: 3,
    title: 'Jaime Joyce',
    job: 'Root canal treatment',
    color: '#cb3939',
  },
  {
    id: 'job5',
    start: '2026-10-22T13:00',
    end: '2026-10-22T14:00',
    resource: 3,
    title: 'Corey Shepard',
    job: 'Tooth extraction',
    color: '#aba343',
  },
  {
    id: 'job6',
    start: '2026-10-22T14:00',
    end: '2026-10-22T16:00',
    resource: 4,
    title: 'Callie Leonard',
    job: 'Crown and bridge',
    color: '#1ca11a',
  },
  {
    id: 'job7',
    start: '2026-10-22T17:00',
    end: '2026-10-22T18:00',
    resource: 4,
    title: 'Harley Thomson',
    job: 'Tartar removal',
    color: '#a446b5',
  },
  {
    id: 'job8',
    start: '2026-10-22T09:00',
    end: '2026-10-22T11:00',
    resource: 6,
    title: 'Ricky Welch',
    job: 'Wisdom tooth removal',
    color: '#334ab9',
  },
];

for (var i = 0; i < myData.length; ++i) {
  var event = myData[i];
  // Convert dates to date objects
  event.start = event.start ? new Date(event.start) : event.start;
  event.end = event.end ? new Date(event.end) : event.end;
  // Mark past events as fixed by setting the event.editable property to false
  event.editable = event.start && today < event.start;
}

var myCalendar = mobiscroll.eventcalendar('#md-docs-appointment-calendar', {
  view: {
    scheduler: {
      type: 'day',
      startTime: '08:00',
      endTime: '20:00',
      allDay: false,
    },
  },
  data: myData,
  resources: [
    {
      id: 1,
      name: 'Dr. Keila Delores',
    },
    {
      id: 2,
      name: 'Dr. Gene Cortez',
    },
    {
      id: 3,
      name: 'Dr. Paula Bush',
    },
    {
      id: 4,
      name: 'Dr. Pete Nichols',
    },
    {
      id: 5,
      name: 'Dr. Jean Pearson',
    },
    {
      id: 6,
      name: 'Dr. Thelma Cain',
    },
  ],
  invalid: [
    {
      recurring: {
        repeat: 'daily',
        until: yesterday,
      },
    },
    {
      start: yesterday,
      end: today,
    },
  ],
  dragToMove: true,
  dragToCreate: true,
  eventOverlap: false,
  externalDrop: true,
  externalDrag: true,
  extendDefaultEvent: function () {
    return {
      job: 'Tartar removal',
      color: '#a446b5',
    };
  },
  onEventCreate: function (args) {
    var event = args.event;
    event.unscheduled = false;
    myCalendar.setOptions({
      colors: [],
    });
  },
  onEventCreated: function (args) {
    mobiscroll.toast({
      message: args.event.title + ' added',
    });
    var elm = document.getElementById('md-event-' + args.event.id);
    if (elm) {
      elm.remove();
    }
  },
  onEventCreateFailed: function (args) {
    if (!(today < args.event.start)) {
      mobiscroll.toast({
        message: "Can't add event in the past",
      });
    } else {
      mobiscroll.toast({
        message: 'Make sure not to double book',
      });
    }
  },
  onEventUpdateFailed: function () {
    mobiscroll.toast({
      message: 'Make sure not to double book',
    });
  },
  onEventDelete: function (args) {
    mobiscroll.toast({
      message: args.event.title + ' unscheduled',
    });
  },
  onEventDragEnter: function () {
    myCalendar.setOptions({
      colors: [
        {
          background: '#f1fff24d',
          start: '08:00',
          end: '20:00',
          recurring: {
            repeat: 'daily',
          },
        },
      ],
    });
  },
  onEventDragLeave: function () {
    myCalendar.setOptions({
      colors: [],
    });
  },
});

mobiscroll.dropcontainer('#md-docs-appointment-cont', {
  onItemDrop: function (args) {
    if (args.data) {
      var event = args.data;
      var eventLength = Math.abs(new Date(event.end) - new Date(event.start)) / (60 * 60 * 1000);
      var elm = document.createElement('div');

      elm.setAttribute('id', 'md-event-' + event.id);
      elm.classList.add('docs-appointment-task');
      elm.style.background = event.color;
      elm.innerHTML =
        '<div>' + event.title + ' - ' + event.job + '</div><div>' + eventLength + ' hour' + (eventLength > 1 ? 's' : '') + '</div>';

      event.unscheduled = true;

      document.getElementById('md-docs-tasks').appendChild(elm);

      mobiscroll.draggable('#md-event-' + event.id, {
        dragData: event,
      });
    }
    externalCont.style.backgroundColor = '';
  },
  onItemDragEnter: function (args) {
    if (!(args.data && args.data.unscheduled)) {
      externalCont.style.backgroundColor = '#d0e7d2cc';
    }
  },
  onItemDragLeave: function () {
    externalCont.style.backgroundColor = '';
  },
});
  

Duplicate Session

You have signed in on a different machine. To keep everything in sync, you have been signed out of this session.

If you need to invite team members, manage seats and accounts you can do it from the licenses page.

Duplicate Session

We noticed you are logged in on a different machine and have closed your old session.

If you need to invite team members, manage seats and accounts you can do it from the licenses page.