Overview

  • Vue.js appointment calendar created using DayPilot JavaScript calendar component from the free and open-source DayPilot Lite scheduling library (Apache License 2.0).

  • How to create and configure the Vue.js calendar

  • How to load event/appointment data

  • How to add support for adding new appointment using drag and drop

  • How to style calendar appointments using CSS

Vue.js Calendar Component

vue js appointment calendar component initialization open source

Let's start with a blank Vue project. We will create a new component that displays an appointment calendar using DayPilot Vue.js Calendar.

The Vue.js Calendar component is included in the Vue.js package of DayPilot Lite for JavaScript. You can install it using using npm:

npm install @daypilot/daypilot-lite-vue

First, we create a new Calendar component using <DayPilotCalendar> tag. Our calendar component will define the scheduler appearance and behavior:

components/Calendar.vue

<template>
  <DayPilotCalendar />
</template>

<script setup>
import {DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
</script>

Now we can add the calendar to our Vue application:

App.vue

<template>
  <Calendar />
</template>

<script setup>
import Calendar from './components/Calendar.vue'
</script>

Tip: If you want to display a calendar for multiple resources (displayed as columns), take a look at the Vue Resource Calendar (Open-Source) tutorial.

Vue.js Weekly Calendar Configuration

vue js weekly calendar component open source

By default, the Vue calendar displays a day view. We want to switch it to a week view. This can be done by setting the viewType property to "Week"

The calendar properties can be specified using the :config attribute of the component. We have set the value to "calendarConfig" which tells the calendar to look for calendarConfig object in the application data.

<template>
  <DayPilotCalendar :config="calendarConfig" />
</template>

<script setup>
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';

const calendarConfig = reactive({
  viewType: "Week",
});

</script>

You can use the config object to set additional calendar properties and event handlers. Changes made to the config object using Vue.set() method will be detected by Vue and the Calendar component will be updated automatically.

Loading Appointments

vue js weekly calendar component open source loading events

In order to load events we need to access the calendar object (DayPilot.Calendar class) and use its API. This object is saved as control property of the Vue.js component.

To access the DayPilotCalendar component object, we will add a calendarRef object to our Vue.js application. Then we can add a ref attribute to the <DayPilotCalendar> tag, pointing to the calendarRef object. Vue will use it to store the component reference.

<template>
  <DayPilotCalendar :config="calendarConfig" ref="calendarRef" />
</template>

<script setup>
import {DayPilot, DayPilotCalendar} from '@daypilot/daypilot-lite-vue';
import { ref, reactive, onMounted } from 'vue';

const calendarConfig = reactive({
  viewType: "Week",
});

const calendarRef = ref(null);

</script>

The appointment data can be displayed using update() method. The update() methods accepts an object with calendar properties to be updated. It loads the properties and redraws the calendar UI.

<template>
  <DayPilotCalendar :config="calendarConfig" ref="calendarRef" />
</template>

<script setup>
import {DayPilot, DayPilotCalendar, DayPilotNavigator} from '@daypilot/daypilot-lite-vue';
import { ref, reactive, onMounted } from 'vue';

const calendarConfig = reactive({
  viewType: "Week",
});

const calendarRef = ref(null);

const loadEvents = () => {
  const events = [
    {
      id: 1,
      start: "2025-02-24T10:00:00",
      end: "2025-02-24T11:00:00",
      text: "Event 1",
    },
    {
      id: 2,
      start: "2025-02-24T13:00:00",
      end: "2025-02-24T16:00:00",
      text: "Event 2",
    },
    // ...
  ];
  calendarRef.value.control.update({events});
};

onMounted(() => {
  loadEvents();
});
</script>

Instead of using the update() method, you can also load the events by modifying the events property of the calendarConfig object:

calendarConfig.events = events;

Creating New Appointments

vue js weekly calendar component open source create event

The JavaScript calendar lets users create new appointments using drag and drop time range selection.

To handle the user action, we'll add onTimeRangeSelected event handler to the calendarConfig object.

<script setup>
import {DayPilot, DayPilotCalendar, DayPilotNavigator} from '@daypilot/daypilot-lite-vue';
import { ref, reactive, onMounted } from 'vue';

const calendarConfig = reactive({
  viewType: "Week",
  onTimeRangeSelected: async (args) => {
    const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
    const dp = args.control;
    dp.clearSelection();
    if (modal.canceled) {
      return;
    }
    dp.events.add({
      start: args.start,
      end: args.end,
      id: DayPilot.guid(),
      text: modal.result
    });
  },
  
  // ...
});

const calendarRef = ref(null);

// ...

</script>

Calendar Appointment CSS Styling

vue js weekly calendar component open source css styling

You can change the appointment appearance using CSS:

  • You can generate a custom CSS theme using the online theme designer. The theme designer lets you customize the appearance of the calendar component and also the styling of the appointments.

  • You can simply override selected styles of the built-in theme.

First, we turn off the duration bar using the configuration object:

const calendarConfig = reactive({

  // ...
  
  durationBarVisible: false,
  
  // ...
  
});

Now we can add custom CSS styles. This CSS class will change the appointment background color to blue, text color to white, add a bit of transparency and apply rounded corners:

<style>
.calendar_default_event_inner {
  background: #2e78d6;
  color: white;
  border-radius: 5px;
  opacity: 0.9;
}
</style>

In addition to the global CSS settings, you can also set selected properties directly in the event properties or you can customize the appointments dynamically using onBeforeEventRender event handler.

const loadEvents = () => {
  const events = [
    {
      id: 1,
      start: "2025-02-24T10:00:00",
      end: "2025-02-24T11:00:00",
      text: "Event 1",
      backColor: "#8cc990",
      borderColor: "#6aa84f",
    },
    {
      id: 2,
      start: "2025-02-24T13:00:00",
      end: "2025-02-24T16:00:00",
      text: "Event 2",
      backColor: "#ffd966",
      borderColor: "#f1c232",
    },
    {
      id: 3,
      start: "2025-02-25T13:30:00",
      end: "2025-02-25T16:30:00",
      text: "Event 3",
      backColor: "#e57373",
      borderColor: "#cc4125",
    },
    {
      id: 4,
      start: "2025-02-25T10:30:00",
      end: "2025-02-25T12:30:00",
      text: "Event 4",
      backColor: "#a4a4a4",
      borderColor: "#7f7f7f",
    },
  ];
  calendarConfig.events = events;
};

Complete Source Code of the Vue.js Calendar Component

components/Calendar.vue

<template>
  <div class="wrap">
    <div class="left">
      <DayPilotNavigator :config="navigatorConfig" />
    </div>
    <div class="content">
      <DayPilotCalendar :config="calendarConfig" ref="calendarRef" />
    </div>
  </div>
</template>

<script setup>
import {DayPilot, DayPilotCalendar, DayPilotNavigator} from '@daypilot/daypilot-lite-vue';
import { ref, reactive, onMounted } from 'vue';

const navigatorConfig = reactive({
  selectMode: "Week",
  showMonths: 3,
  skipMonths: 3,
  startDate: "2025-03-01",
  selectionDay: "2025-02-28",
  onTimeRangeSelected: args => {
    calendarConfig.startDate = args.day;
  }
});

const calendarConfig = reactive({
  viewType: "Week",
  startDate: "2025-02-28",
  durationBarVisible: false,
  timeRangeSelectedHandling: "Enabled",
  onTimeRangeSelected: async (args) => {
    const modal = await DayPilot.Modal.prompt("Create a new event:", "Event 1");
    const dp = args.control;
    dp.clearSelection();
    if (modal.canceled) {
      return;
    }
    dp.events.add({
      start: args.start,
      end: args.end,
      id: DayPilot.guid(),
      text: modal.result
    });
  },
  contextMenu: new DayPilot.Menu({
    items: [
      {text: "Delete", onClick: args => {
        const dp = calendarRef.value.control;
        dp.events.remove(args.source);
      }}
    ]
  }),
  onBeforeEventRender: args => {
    args.data.areas = [
      {
        right: 5,
        top: 7,
        width: 25,
        height: 25,
        backColor: "#ffffff",
        fontColor: "#666666",
        padding: 4,
        symbol: "/icons/daypilot.svg#threedots-v",
        style: "border-radius: 50%;",
        action: "ContextMenu",
      }
    ];
  },
  eventDeleteHandling: "Disabled",
  onEventMoved: () => {
    console.log("Event moved");
  },
  onEventResized: () => {
    console.log("Event resized");
  },
});

const calendarRef = ref(null);

const loadEvents = () => {
  const events = [
    {
      id: 1,
      start: "2025-02-24T10:00:00",
      end: "2025-02-24T11:00:00",
      text: "Event 1",
      backColor: "#6aa84f",
      borderColor: "#569838",
    },
    {
      id: 2,
      start: "2025-02-24T13:00:00",
      end: "2025-02-24T16:00:00",
      text: "Event 2",
      backColor: "#f1c232",
      borderColor: "#d5a715",
    },
    {
      id: 3,
      start: "2025-02-25T13:30:00",
      end: "2025-02-25T16:30:00",
      text: "Event 3",
      backColor: "#da5c41",
      borderColor: "#cc4125",
    },
    {
      id: 4,
      start: "2025-02-25T10:30:00",
      end: "2025-02-25T12:30:00",
      text: "Event 4",
    },
  ];
  calendarConfig.events = events;
};

onMounted(() => {
  loadEvents();
});
</script>

<style>
.wrap {
  display: flex;
}

.left {
  margin-right: 10px;
}

.content {
  flex-grow: 1;
}


.calendar_default_event_inner {
  background: #2e78d6;
  border-color: #0a5cd2;
  color: white;
  border-radius: 5px;
  opacity: 0.9;
}
</style>

History