Overview

  • The Vue resource calendar component displays resources (people, rooms, cars, tools) as columns.

  • It is built using the open-source Vue calendar from DayPilot Lite for JavaScript package.

  • You can switch the current day using a date picker that shows a calendar preview for three months.

  • Days with scheduled events are highlighted in the date picker.

  • You can define custom columns as necessary.

  • The resource calendar lets you schedule tasks, make reservations, and show resource utilization.

  • Vue calendar project is available for download.

License

Apache License 2.0

Resource Calendar in Vue.js

To start using the DayPilot resource calendar in you Vue application, install @daypilot/daypilot-lite-vue NPM package:

yarn install @daypilot/daypilot-lite-vue

Now you can add the resource calendar:

  1. Create a new ResourceCalendar Vue component.

  2. Add <DayPilotCalendar> to the component template.

  3. Add a[config] attribute to <DayPilotCalendar> and point it to a config data property.

  4. Add the config object to the component data.

  5. To enable the resource calendar mode, add viewType: "Resources" to the config.

To load resource calendar event data:

  1. Add a ref attribute <DayPilotCalendar> to store a reference to the Calendar component.

  2. For easy access to the DayPilot.Calendar object, add a calendar() method to the computed section. This will let you access the calendar object as this.calendar in your Vue application.

  3. To load events, call the this.calendar.update() with events array in the options parameter. You can use the update() method to update the Calendar component.

ResourceCalendar.js:

<template>
  <DayPilotCalendar id="dp" :config="config" ref="calendar" />
</template>

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

export default {
  name: 'ResourceCalendar',
  data: function() {
    return {
      config: {
        viewType: "Resources",
        startDate: "2022-08-01",
      },
    }
  },
  components: {
    DayPilotCalendar,
  },
  computed: {
    calendar() {
      return this.$refs.calendar.control;
    },
  },
  methods: {
    loadEvents() {
      // placeholder for an HTTP call
      const events = [
        {
          id: 1,
          start: "2022-08-01T10:00:00",
          end: "2022-08-01T11:00:00",
          resource: "R3",
          text: "Event 1",
          barColor: "#6aa84f",
        },
        // ...
      ];
      this.calendar.update({events});
    },
  },
  mounted() {
    this.loadEvents();
  }
}
</script>

Resources as Columns

vue resource calendar open source load columns

As soon as the calendar is initialized, we can load the columns:

mounted() {
  this.loadResources();
}

Our loadResources() method defines a set of resources statically to make things easier:

const columns = [
  {name: "Resource 1", id: "R1"},
  {name: "Resource 2", id: "R2"},
  {name: "Resource 3", id: "R3"},
  {name: "Resource 4", id: "R4"},
  {name: "Resource 5", id: "R5"},
  {name: "Resource 6", id: "R6"},
];

To load the columns, use the update() method of the calendar:

methods: {
  loadResources() {
    const columns = [
      {name: "Resource 1", id: "R1"},
      // ...
    ];
    this.calendar.update({columns});
  },
}

The update() method loads the supplied data and refresh the calendar. The options argument is an object with properties that will be updated. In this case, we only include the columns property that will load the resources but you can update multiple properties at once if needed.

Resource Calendar Events/Tasks

vue resource calendar open source load events tasks

It is also necessary to load the event data (tasks, reservations) that will be displayed in the main calendar grid.

mounted() {
  // ...
  this.loadEvents();
}

The loadEvents() method is also very simple. And again, it uses the update() method to load the data and update the calendar.

methods: {
  loadEvents() {
    // placeholder for an HTTP call
    const events = [
      {
        id: 1,
        start: "2022-08-01T10:00:00",
        end: "2022-08-01T11:00:00",
        resource: "R3",
        text: "Event 1",
        barColor: "#6aa84f",
      },
      {
        id: 2,
        start: "2022-08-01T13:00:00",
        end: "2022-08-01T16:00:00",
        resource: "R3",
        text: "Event 2",
        barColor: "#f1c232",
      },
      // ...
    ];
    this.calendar.update({events});
  },
}

Add New Events using Drag and Drop

vue resource calendar new event

The resource calendar supports adding new events using drag and drop. User can select a time range for the selected resource (column) and enter details of the new event.

To enable this feature, add an onTimeRangeSelected event handler to the calendar config:

data: function() {
  return {
    calendarConfig: {
      timeRangeSelectedHandling: "Enabled",
      onTimeRangeSelected: async (args) => {
        await this.createEvent(args.start, args.end, args.resource);
        this.calendar.clearSelection();
      },
    },
    // ...
  }
}

The createEvent() method opens a modal dialog that shows the selected resource, start and end time and lets you type the event text.

The modal dialog is created using DayPilot.Modal.form() method that lets you create a modal dialog with custom form fields programmatically (see also some modal dialog examples).

vue resource calendar event details modal dialog

Our “new event” form displays four fields:

  • Text

  • Start

  • End

  • Resources

The DayPilot.Modal.form() method can pre-fill the form fields from the supplied data object. The data object uses data from the current calendar selection (start, end, resource).

As soon as the modal dialog closes, you can access the form result using modal.result property. It’s a copy of the original data object - the properties are updated using the supplied form field values.

methods: {
  async createEvent(start, end, resource) {
    const form = [
      {name: "Text", id: "text"},
      {name: "Start", id: "start", type: "datetime", disabled: true},
      {name: "End", id: "end", type: "datetime", disabled: true},
      {name: "Resource", id: "resource", type: "select", options: this.calendar.columns.list}
    ];
    const data = {
      start,
      end,
      resource,
      id: DayPilot.guid()
    };
    const modal = await DayPilot.Modal.form(form, data);
    if (modal.canceled) {
      return;
    }

    const e = modal.result;
    this.calendar.events.add(e);
  },
  // ...
}

The events.add() method adds the new event to to resource calendar.

Edit Resource Calendar Events

You can use the same method to create the “edit” modal dialog.

To open the modal dialog on event click, it is necessary to add an onEventClick event handler to the resource calendar config:

data: function() {
  return {
    calendarConfig: {
      onEventClick: (args) => {
        this.editEvent(args.e);
      },

      // ...

    },
  }
}

The editEvent() method opens a modal dialog similar to the “new event” dialog from the previous chapter and updates the event using events.update() call.

methods: {
  async editEvent(e) {
    const form = [
      {name: "Text", id: "text"},
      {name: "Start", id: "start", type: "datetime", disabled: true},
      {name: "End", id: "end", type: "datetime", disabled: true},
      {name: "Resource", id: "resource", type: "select", options: this.calendar.columns.list}
    ];
    const data = e.data;
    const modal = await DayPilot.Modal.form(form, data);
    if (modal.canceled) {
      return;
    }

    this.calendar.events.update(modal.result);

  },
  
  // ...
  
}

Vue Date Picker with Free/Busy Highlighting

vue resource calendar open source date picker

To make the date switching easier, we will add a date picker component that will display an overview of three months and let users change the current date easily. To learn more about the Vue date picker, please see the Vue Date Picker with Free/Busy Highlighting (Open-Source) tutorial. Here is a quick summary of the necessary steps:

The date picker can be added using <DayPilotNavigator> component.

First, it’s necessary to update the layout so there are two independent columns. The left column will display the date picker component and the right column will display the resource calendar:

<template>
  <div class="wrap">
    <div class="left">
      <DayPilotNavigator id="nav" :config="navigatorConfig" ref="navigator" />
    </div>
    <div class="content">
      <DayPilotCalendar id="dp" :config="config" ref="calendar" />
    </div>
  </div>
</template>

The parent <div> that is marked with wrap CSS class uses display: flex to show the child elements as columns:

<style>
.wrap {
  display: flex;
}

.left {
  margin-right: 10px;
}

.content {
  flex-grow: 1;
}

</style>

Now we can configure the date picker:

data: function() {
  return {
    navigatorConfig: {
      showMonths: 3,
      skipMonths: 3,
      selectMode: "Day",
      startDate: "2022-08-01",
      selectionDay: "2022-08-01",
      onTimeRangeSelected: args => {
        this.calendarConfig.startDate = args.day;
      }
    },
  }
},

To highlight busy days, load the event data:

methods: {
  loadEvents() {
    // placeholder for an HTTP call
    const events = [
      {
        id: 1,
        start: "2022-08-01T10:00:00",
        end: "2022-08-01T11:00:00",
        resource: "R3",
        text: "Event 1",
        barColor: "#6aa84f",
      },
      // ...
    ];
    this.navigator.update({events});
  },
}

The navigator computed property provides access to the DayPilot.Navigator object:

computed: {
  navigator() {
    return this.$refs.navigator.control;
  },
  // ...
}