Overview

In the Vue Calendar component of the open-source DayPilot library, you can use Vue templates to insert custom content into calendar elements (including events and grid cells).

In this tutorial, we'll explore how to use Vue templates to add dynamic content to calendar slots:

  • Display the slot start time (in HH:mm format) at the center of each time slot.

  • Add a sun icon to cells at sunrise.

  • Add a moon icon to cells at sunset.

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. Buy a license.

Use Vue Templates to Customize Calendar Slots

Use Vue Templates to Customize Calendar Slots - Open-Source Vue Calendar

As soon as you have the Vue calendar configured in your Vue app, you can add a template to define custom slot content.

<template>
  <DayPilotCalendar
    :viewType="'Week'"
    :startDate="startDate"
    :events="events"
  >
    <template #cell="{cell}">
      <div class="cell">
        {{cell.start.toString("hh:mm tt")}}
      </div>
    </template>
  </DayPilotCalendar>
</template>

The template receives an args object with a cell property which holds the cell details.

You can use the cell object to access the cell start and end (as DayPilot.Date objects). To print the cell start, we will use cell.start.toString():

{{cell.start.toString("hh:mm tt")}}

The cell CSS class expands the <div> size to fill the whole cell and centers the content vertically and horizontally:

.cell {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  inset: 0;
  color: #e0e0e0;
  cursor: pointer;
}

In addition to Vue templates, you can also use the onBeforeCellRender event to customize calendar cells (set business status, background color, CSS class, add active areas with icons).

Adding a Sun Icon to the Sunrise Cell

Adding a Sun Icon to the Sunrise Cell - Open-Source Vue Calendar

You can also add conditional content. This example adds a “sun” icon to any cell containing the sunrise time.

Let’s define the following list of sunrise and sunset times:

const sun = [
  { day: "2025-12-28", sunrise: new DayPilot.Date("2025-12-28T08:01:00"), sunset: new DayPilot.Date("2025-12-28T15:59:00") },
  { day: "2025-12-29", sunrise: new DayPilot.Date("2025-12-29T08:01:00"), sunset: new DayPilot.Date("2025-12-29T16:00:00") },
  { day: "2025-12-30", sunrise: new DayPilot.Date("2025-12-30T08:00:00"), sunset: new DayPilot.Date("2025-12-30T16:00:00") },
  { day: "2025-12-31", sunrise: new DayPilot.Date("2025-12-31T07:59:00"), sunset: new DayPilot.Date("2025-12-31T16:01:00") },
  { day: "2026-01-01", sunrise: new DayPilot.Date("2026-01-01T07:59:00"), sunset: new DayPilot.Date("2026-01-01T16:01:00") },
  { day: "2026-01-02", sunrise: new DayPilot.Date("2026-01-02T07:59:00"), sunset: new DayPilot.Date("2026-01-02T16:02:00") },
  { day: "2026-01-03", sunrise: new DayPilot.Date("2026-01-03T07:58:00"), sunset: new DayPilot.Date("2026-01-03T16:03:00") },
]

Next, extend the Calendar slot template to check for a corresponding sunrise time. If the sunrise time falls within the current cell, it adds a special <div> with a sun icon:

<template>
  <DayPilotCalendar
    :viewType="'Week'"
    :startDate="startDate"
    :events="events"
  >
    <template #cell="{cell}">

      <!-- ... -->

      <!-- sunrise -->
      <div class="sun" v-if="sun.find(s => s.sunrise >= cell.start && s.sunrise < cell.end)" title="Sunrise">
        &#x2600;&#xFE0F;
      </div>

      <!-- ... -->

    </template>
  </DayPilotCalendar>
</template>

Adding a Moon Icon to the Sunset Cell

Adding a Moon Icon to the Sunset Cell - Open-Source Vue Calendar

The same approach can be used to display a moon icon in the sunset time slots:

<template>
  <DayPilotCalendar
    :viewType="'Week'"
    :startDate="startDate"
    :events="events"
  >
    <template #cell="{cell}">

      <!-- ... -->
    
      <!-- sunset -->
      <div class="sun" v-if="sun.find(s => s.sunset >= cell.start && s.sunset < cell.end)" title="Sunset">
        &#x1F319;
      </div>
      
      <!-- ... -->
      
    </template>
  </DayPilotCalendar>
</template>

Full Source Code

Here is the full source code of our Vue calendar component that customizes the time slots using Vue templates:

<template>
  <DayPilotCalendar
    :viewType="'Week'"
    :startDate="startDate"
    :events="events"
    :eventBorderRadius="5"
    :durationBarVisible="false"
    @beforeEventRender="onBeforeEventRender"
    @timeRangeSelected="onTimeRangeSelected"
    ref="calendarRef"
  >
    <template #cell="{cell}">
      <div class="cell">
        {{cell.start.toString("hh:mm tt")}}
      </div>
      <!-- sunrise -->
      <div class="sun" v-if="sun.find(s => s.sunrise >= cell.start && s.sunrise < cell.end)" title="Sunrise">
        &#x2600;&#xFE0F;
      </div>
      <!-- sunset -->
      <div class="sun" v-if="sun.find(s => s.sunset >= cell.start && s.sunset < cell.end)" title="Sunset">
        &#x1F319;
      </div>
    </template>
  </DayPilotCalendar>
</template>

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

const calendarRef = ref(null)

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

const onBeforeEventRender = (args) => {
  args.data.backColor = "#6aa84fbb"
  args.data.borderColor = "darker"
  args.data.fontColor = "#ffffff"
}

const startDate = ref(new DayPilot.Date("2026-01-01"))

const events = ref([])

const sun = [
  { day: "2025-12-28", sunrise: new DayPilot.Date("2025-12-28T08:01:00"), sunset: new DayPilot.Date("2025-12-28T15:59:00") },
  { day: "2025-12-29", sunrise: new DayPilot.Date("2025-12-29T08:01:00"), sunset: new DayPilot.Date("2025-12-29T16:00:00") },
  { day: "2025-12-30", sunrise: new DayPilot.Date("2025-12-30T08:00:00"), sunset: new DayPilot.Date("2025-12-30T16:00:00") },
  { day: "2025-12-31", sunrise: new DayPilot.Date("2025-12-31T07:59:00"), sunset: new DayPilot.Date("2025-12-31T16:01:00") },
  { day: "2026-01-01", sunrise: new DayPilot.Date("2026-01-01T07:59:00"), sunset: new DayPilot.Date("2026-01-01T16:01:00") },
  { day: "2026-01-02", sunrise: new DayPilot.Date("2026-01-02T07:59:00"), sunset: new DayPilot.Date("2026-01-02T16:02:00") },
  { day: "2026-01-03", sunrise: new DayPilot.Date("2026-01-03T07:58:00"), sunset: new DayPilot.Date("2026-01-03T16:03:00") },
]

const loadEvents = () => {
  events.value = [
    { id: 1, start: "2025-12-29T11:00:00", end: "2025-12-29T14:00:00", text: "Event 1" },
    { id: 2, start: DayPilot.Date.today().addHours(11), end: DayPilot.Date.today().addHours(14), text: "Event 1"}
  ]
}

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

<style scoped>
.cell {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  inset: 0;
  color: #e0e0e0;
  cursor: pointer;
}
.sun {
  position: absolute;
  top: 0;
  right: 0;
  font-size: 20px;
  color: #f0f0f0;
  cursor: default;
}
</style>

You can download the complete Vue project using the download link at the top of the tutorial.