e8-calendar
Updated on Sep 18, 2025 25 minutes to readA flexible and feature-rich calendar component built.
It supports multiple views, event management (create, edit, delete), and customizable popups through slots.
Overview
e8-calendar provides an interactive scheduling interface with support for daily, weekly, monthly, yearly, and list views.
Users can navigate between periods, view events, and manage them with drag-and-drop, resizing, and inline editing.
Custom headers, action buttons, and event popups can be provided via slots for maximum flexibility.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$set(E8App.vars, 'calendarEvents', [
{
id: 'allDay',
allDay: true,
startDate: E8App.$date.addDays(E8App.$date.current(), -1),
endDate: E8App.$date.addDays(E8App.$date.current(), -1),
title: 'All Day Conference',
description: 'A full-day event covering all key topics.',
backgroundColor: '#FF6B6B',
borderColor: '#FF3B3B',
},
{
id: 'todayEvent',
allDay: false,
startDate: E8App.$date.current(),
endDate: E8App.$date.current(),
startTime: '12:00:00',
endTime: '12:59:59',
title: 'Lunch Break',
description: 'Enjoy a relaxing lunch with colleagues.',
backgroundColor: '#4ECDC4',
borderColor: '#3BB6A5',
},
{
id: 'twoDayEvent',
allDay: false,
startDate: E8App.$date.current(),
endDate: E8App.$date.addDays(E8App.$date.current(), 1),
startTime: '13:00:00',
endTime: '18:00:00',
title: 'Tech Innovation Summit',
description: 'Two days of workshops and networking focused on technology trends.',
backgroundColor: '#FFD93D',
borderColor: '#FFC107',
},
{
id: 'morningMeeting',
allDay: false,
startDate: E8App.$date.current(),
endDate: E8App.$date.current(),
startTime: '09:00:00',
endTime: '10:00:00',
title: 'Morning Standup',
description: 'Daily team sync-up meeting.',
backgroundColor: '#6A4C93',
borderColor: '#5A3E7A',
},
{
id: 'eveningYoga',
allDay: false,
startDate: E8App.$date.current(),
endDate: E8App.$date.current(),
startTime: '19:00:00',
endTime: '20:00:00',
title: 'Evening Yoga',
description: 'Relax and unwind with a gentle yoga session.',
backgroundColor: '#FF8C42',
borderColor: '#E57200',
},
{
id: 'projectDeadline',
allDay: false,
startDate: E8App.$date.addDays(E8App.$date.current(), 2),
endDate: E8App.$date.addDays(E8App.$date.current(), 2),
startTime: '17:00:00',
endTime: '17:30:00',
title: 'Project Deadline',
description: 'Submit all deliverables for the project.',
backgroundColor: '#1FAB89',
borderColor: '#138A75',
},
{
id: 'teamBuilding',
allDay: true,
startDate: E8App.$date.addDays(E8App.$date.current(), 3),
endDate: E8App.$date.addDays(E8App.$date.current(), 3),
title: 'Team Building Day',
description: 'Outdoor activities designed to strengthen teamwork.',
backgroundColor: '#3A86FF',
borderColor: '#265DAB',
},
{
id: 'dentistAppointment',
allDay: false,
startDate: E8App.$date.addDays(E8App.$date.current(), 4),
endDate: E8App.$date.addDays(E8App.$date.current(), 4),
startTime: '14:30:00',
endTime: '15:30:00',
title: 'Dentist Appointment',
description: 'Routine dental check-up.',
backgroundColor: '#8338EC',
borderColor: '#5B24A6',
},
]);
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
:popup-on-hover="true"
:height="500"
:year-view="true"
:sticky-header="true"
:sticky-header-dates="true"
min-time="09:00"
max-time="20:00"
year-view-variant="stack"></e8-calendar>
/>
Properties
Property | Description | Type | Default |
---|---|---|---|
all-day | Enables or disables support for all-day events. | boolean | true |
day-slot-height | Height of day slots. Applies only to the year or month view. | string | number | 'auto' |
day-view | Enables daily view mode. | boolean | true |
default-color | Default color applied to events without a specific color. | string | '' |
default-view | The initial calendar view. | CalendarViewVariants | 'week' |
droppable | Allows external elements to be dropped onto the calendar as events. | boolean | true |
event-display | Defines how events are displayed (block , list-item , etc.). | CalendarEventDisplaysVariants | 'block' |
event-limit | Limits the number of events per day cell. | string | number | bool | true |
events | Array of event objects rendered on the calendar. | CalendarEvents[] | [] |
height | Calendar height (auto , number, or CSS string). | string | number | 'auto' |
hidden-days | Array of weekday indices (0–6) to hide. | array | [] |
list-view | Enables list view mode. | boolean | true |
max-time | Defines the maximum visible time in a day. | E8Time | '24:00:00' |
min-time | Defines the minimum visible time in a day. | E8Time | '00:00:00' |
month-view | Enables monthly view mode. | boolean | true |
popup-max-width | Maximum width of the event popup. | string | number | '25rem' |
popup-min-width | Minimum width of the event popup. | string | number | '' |
popup-on-hover | Show popup on hover instead of click. | boolean | false |
readonly | Disables event editing and drag-and-drop. | boolean | false |
selectable | Allows selecting time ranges on the calendar. | boolean | true |
sticky-header | Enables sticky positioning for the header. | boolean | false |
sticky-header-dates | Makes header dates sticky during scrolling. | boolean | false |
week-view | Enables weekly view mode. | boolean | true |
year-view | Enables yearly view mode. | boolean | false |
year-view-variant | Controls the layout of the year view (e.g., continuous). | CalendarYearViewVariants | 'continuous' |
Slots
Slot | Description |
---|---|
actions | Custom action buttons in the calendar header. |
event | Custom rendering of an event inside the calendar. |
popup-actions | Custom action buttons inside the event popup. |
popup-title | Custom event title inside the popup. |
popup-range | Custom event date/time range inside the popup. |
popup-description | Custom event description inside the popup. |
Events
Event | Description |
---|---|
on-change-event | Triggered when an event is updated. |
on-change-period | Triggered when the visible calendar period changes. |
on-delete-event | Triggered when an event is deleted. |
on-drop-event | Triggered when an event is moved (drag & drop). |
on-edit-event | Triggered when an event is opened for editing. |
on-render-day-slot | Triggered before an event is rendered. |
on-render-event | Triggered before a day slot is rendered. |
on-resize-event | Triggered when an event duration is resized. |
on-select-range | Triggered when a time/date range is selected. |
Details
All Day Events
Enables all-day slot display for events. This slot is only visible in day and week views.
Default: true
Day Slot Height
Sets a fixed height for each day slot in the calendar. Applied only in year and month views.
Accepted values include numeric values (pixels), CSS length units (e.g., "100px", "2rem"), or "auto" to let the slot height adjust automatically.
Default: 'auto'
Day View
Show day view button in the calendar toolbar.
Default: true
Default Color
Default color used for events without specified colors. Accepts HEX codes or CSS color names.
Default: ''
Default View
Initial calendar view.
Default: 'timeGridWeek'
Droppable
Allows external events to be dropped onto the calendar.
Default: true
⚠️ Only events that extend the CalendarEvent interface are supported.
Event Display
Display mode for events.
Default: 'block'
E8App.vars.displayEvents = [
{
id: 1,
title: 'Event',
startDate: E8App.$date.addDays(E8App.$date.current(), -1),
endDate: E8App.$date.addDays(E8App.$date.current(), -1),
startTime: '11:00:00',
endTime: '13:00:00',
}
];
Event Limit
Controls how many events are displayed per day before showing a “+N more” link in month or week views:
- true — uses the default limit defined by the calendar (automatically determined by the cell height).
- false — do not limit events; all events are shown.
- number — show up to that many events per day, excess events will be hidden under the “+N more” link.
- string — numeric values as string (e.g., "3") are treated as a number limit.
Default : true
E8App.vars.limitEvents = Array.from({ length: 23 }, (_, i) => {
let date = E8App.$date.current();
if (i % 2 === 0) {
date = E8App.$date.addDays(date, -1)
}
if (i % 3 === 0) {
date = E8App.$date.addDays(date, 1)
}
if (i % 5 === 0) {
date = E8App.$date.addWeeks(date, -1)
}
return {
id: i,
title: `Event ${i}`,
startDate: date,
endDate: date,
startTime: `${i < 10 ? '0' + i : i}:00:00`,
endTime: `${i < 10 ? '0' + i : i}:59:59`,
}
});
Events
An array of objects that extend the CalendarEvent interface, rendered in the calendar.
Default: []
Hidden Days
Array of days to hide in the calendar. 0 = Sunday, 6 = Saturday.
Default: []
Height
Calendar height. Can be 'auto' or a fixed value (pixels or CSS units)
Default: 'auto'
List View
Show list view button in the calendar toolbar.
Default: true
Max Time
Maximum time displayed in time grid views.
Default: '24:00:00'
Min Time
Minimum time displayed in time grid views.
Default: '00:00:00'
Month View
Show month view button in the calendar toolbar.
Default: true
Popup Max Width
Maximum width of event popup. Can be pixels, rem, or other CSS units.
Default: '25rem'
Popup Min Width
Minimum width of event popup. Can be pixels, rem, or other CSS units.
Default: ''
Popup On Hover
Show event popup on hover instead of click.
Default: false
Readonly
Makes all events read-only and disables editing.
Default: false
Selectable
Enables selecting date or time ranges directly on the calendar by dragging or clicking.
When selectable
is true
, users can select a range of dates (or hours in day/week views), and the on-select-range
event will be triggered with details about the selected start and end.
This is useful for creating new events, highlighting periods, or implementing custom actions when a range is selected.
Default: false
Sticky Header
Enables a sticky header for the calendar.
When sticky-header
is true
, the top part of the calendar containing action buttons (view switches, today/prev/next buttons, etc.) and the date headers remain fixed when scrolling through the calendar content.
This ensures that controls and dates are always visible even when viewing long lists of events or month/day grids.
Default: false
⚠️ When sticky-header
is true
, it automatically includes sticky behavior for the dates, so sticky-header-dates
does not need to be enabled separately.
Sticky Header Dates
Enables a sticky header specifically for the date row(s) in month and week views.
When sticky-header-dates
is true
and sticky-header
is not enabled, the date labels at the top of the calendar grid remain visible while scrolling.
Default: false
⚠️ If sticky-header
is true
, sticky-header-dates
is automatically applied and does not need to be set.
Week View
Show week view button in the calendar toolbar.
Default: true
Year View
Show year view button in the calendar toolbar.
Default: false
Year View Variant
Variant of year view.
Default: 'continuos'
Event: On Change Event
Triggered when an event is modified by drag-and-drop or resize.
Receives eventData
(from the provided events
array) containing the updated event.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onChangeEvent', (eventData) => {
console.log('Updated event:', eventData)
});
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
on-change-event="onChangeEvent"
></e8-calendar>
Event: On Change Period
Triggered when the visible period of the calendar changes (for example, when navigating to another week or month).
Receives four arguments:
startDate
— visible range start as E8DateendDate
— visible range end as E8Datestart
— visible range start as E8Timestampend
— visible range end as E8Timestamp
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onChangePeriod', (startDate, endDate, start, end) => {
console.log('Visible period:', startDate, endDate, start, end);
});
Copy this snippet into the Content section
<e8-calendar
on-change-period="onChangePeriod"
></e8-calendar>
Event: On Delete Event
Triggered when an event is deleted from the calendar.
Receives eventData
(from the provided events
array) of the deleted event.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onDeleteEvent', (eventData) => {
console.log('Deleted event:', eventData);
});
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
on-delete-event="onDeleteEvent"
></e8-calendar>
Event: On Drop Event
Triggered when an external event is dropped onto the calendar.
Receives eventData
(from the provided events
array) of the dropped item.
External events must follow the same event object structure as the calendar’s events prop.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onDropEvent', (eventData) => {
console.log('Dropped event:', eventData);
});
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
on-drop-event="onDeleteEvent"
></e8-calendar>
Event: On Edit Event
Triggered when an event is double-clicked (or otherwise opened for editing).
Receives eventData
(from the provided events
array) of the clicked event.
Useful for opening custom edit dialogs.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onEditEvent', (eventData) => {
console.log('Edit event:', eventData)
});
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
on-edit-event="onEditEvent"
></e8-calendar>
Event: On Render Day slot
Triggered when a day slot is being rendered in the calendar.
This event can be used to customize the appearance of specific days.
Two main options are available:
1️⃣ Set background color via event data — by overriding the backgroundColor property of eventData.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onRenderDaySlot', (eventData, el) => {
if (E8App.$date.day(eventData.stardDate) % 2) {
eventData.backgroundColor = 'salmon';
}
});
Copy this snippet into the Content section
<e8-calendar
on-render-day-slot="onRenderDaySlot"
></e8-calendar>
2️⃣ Modify the rendered DOM element — the el parameter can be accessed and changed with standard JavaScript (e.g., adding classes, inline styles, or attributes) before the slot is displayed.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onRenderDaySlot', (eventData, el) => {
if (E8App.$date.day(eventData.stardDate) % 2) {
info.el.style.backgroundColor = 'salmon';
}
});
Copy this snippet into the Content section
<e8-calendar
on-render-day-slot="onRenderDaySlot"
></e8-calendar>
Event: Render Event
Triggered when an event element is being rendered in the calendar.
Receives eventData
(from the provided events
array) with updated start and end values.
This event is intended for programmatic modification of the rendered DOM element (el) before it is displayed.
You can:
- Apply inline styles
- Add or remove CSS classes
- Insert additional child elements
- Customize the structure or attributes of the event node
This provides full control over the visual presentation of events beyond what props and slots allow.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onRenderEvent', (eventData, el) => {
if (eventData.startDate < E8App.$date.current()) {
info.el.style.border = '2px solid gold'
info.el.style.padding = '4px'
// Add custom icon inside the event element
const icon = document.createElement('i')
icon.className = 'e8i e8i-star-fill'
icon.style.marginRight = '4px'
info.el.prepend(icon)
}
});
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
on-render-event="onRenderEvent"
></e8-calendar>
Event: On Resize Event
Triggered when an event is resized in the calendar.
Receives eventData
(from the provided events
array) with updated start and end values.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onResizeEvent', (eventData) => {
console.log('Resized event:', eventData);
});
Copy this snippet into the Content section
<e8-calendar
:events="vars.calendarEvents"
on-resize-event="onResizeEvent"
></e8-calendar>
Event: On Select Range
Triggered when the user selects a date or time range on the calendar (via click or drag).
Receives startDate
and endDate
of the selected range.
Useful for creating new events or highlighting ranges.
Insert this code into Main or Initialization script of the form to register a global method
E8App.$methods.set('onSelectRange', (startDate, endDate) => {
console.log('Selected:', startDate, 'to', endDate)
});
Copy this snippet into the Content section
<e8-calendar
on-select-range="onSelectRange"
></e8-calendar>
Slot: Actions
Slot for rendering custom action buttons in the calendar header (next to the "Today" and navigation buttons).
<e8-calendar height="100px">
<template #actions>
<e8-button variant="success" size="small">Custom Action</e8-button>
</template>
</e8-calendar>
Slot: Event
Custom slot for rendering event content inside the calendar.
Receives event
argument, which corresponds to eventData
from the provided events
array.
<e8-calendar
height="300px"
:events="vars.calendarEvents"
>
<template #event="{ event }">
<div>
<strong>{{ event.title }}</strong>
<small>{{ event.description }}</small>
</div>
</template>
</e8-calendar>
Slot: Popup Actions
Custom slot for rendering event content inside the calendar.
Receives event
argument, which corresponds to eventData
from the provided events
array.
<e8-calendar
height="300px"
:events="vars.calendarEvents"
>
<template #popup-actions="{ event }">
<e8-button size="small">Custom</e8-button>
</template>
</e8-calendar>
Slot: Popup Title
Slot for customizing the event title inside the popup.
Receives event
argument, which corresponds to eventData
from the provided events
array.
<e8-calendar
height="300px"
:events="vars.calendarEvents"
>
<template #popup-title="{ event }">
<h4 style="color: salmon">{{ event.title }}</h4>
</template>
</e8-calendar>
{{ event.title }}
Slot: Popup Range
Slot for customizing the event date/time range inside the popup.
Receives event
argument, which corresponds to eventData
from the provided events
array.
<e8-calendar
height="300px"
:events="vars.calendarEvents"
>
<template #popup-range="{ event }">
<span>🗓 {{ event.startDate }} → {{ event.endDate }}</span>
</template>
</e8-calendar>
Slot: Popup Description
Slot for customizing the event description inside the popup.
Receives event
argument, which corresponds to eventData
from the provided events
array.
<e8-calendar
height="300px"
:events="vars.calendarEvents"
>
<template #popup-description="{ event }">
<p style="white-space: pre-line; color: gray">
{{ event.description || 'No description' }}
</p>
</template>
</e8-calendar>
{{ event.description || 'No description' }}