Custom Events Reference
All custom DOM events fired by <lms-calendar> and its child components. Every event uses bubbles: true and composed: true, so you can listen on the <lms-calendar> host element from any framework.
const calendar = document.querySelector('lms-calendar');
calendar.addEventListener('switchview', (e) => {
console.log('View changed to', e.detail.view);
});
switchdate
Fired when the user navigates forward or backward via header buttons.
| Property | Value |
|---|---|
| Source | <lms-calendar-header> |
| Bubbles | true |
| Composed | true |
| Detail | { direction: 'next' | 'previous' } |
calendar.addEventListener('switchdate', (e) => {
analytics.track('calendar_navigate', { direction: e.detail.direction });
});
switchview
Fired when the user switches between view modes (day, week, month, year) via header buttons.
| Property | Value |
|---|---|
| Source | <lms-calendar-header> |
| Bubbles | true |
| Composed | true |
| Detail | { view: 'day' | 'week' | 'month' | 'year' } |
calendar.addEventListener('switchview', (e) => {
console.log('Now showing', e.detail.view);
});
jumptoday
Fired when the user clicks the "Today" button in the header.
| Property | Value |
|---|---|
| Source | <lms-calendar-header> |
| Bubbles | true |
| Composed | true |
| Detail | { date: CalendarDate } |
calendar.addEventListener('jumptoday', (e) => {
myRouter.navigate(`/schedule/${e.detail.date.year}/${e.detail.date.month}`);
});
expand
Fired when the user clicks a day label, day cell, week number, or month label to drill into a more detailed view. The detail payload varies by source:
| Source | detail.drillTarget |
Notes |
|---|---|---|
| Month view (day click) | not present | Only { date } is provided |
| Week view (day label click) | not present | Only { date } is provided |
| Year view (day click) | this.drillTarget value |
Reflects the yearDrillTarget property |
| Year view (week click) | 'week' |
Always drills to week view |
| Year view (month label click) | 'month' |
Always drills to month view |
| Property | Value |
|---|---|
| Source | <lms-calendar-month>, <lms-calendar-week>, <lms-calendar-year> |
| Bubbles | true |
| Composed | true |
| Detail | { date: CalendarDate, drillTarget?: 'day' | 'week' | 'month' } |
calendar.addEventListener('expand', (e) => {
const { date, drillTarget } = e.detail;
if (drillTarget === 'day') {
router.push(`/schedule/${date.year}/${date.month}/${date.day}`);
}
});
Tip: Check for the presence of
drillTargetto distinguish between month/week clicks (no target) and year-view clicks (always has a target).
open-menu
Fired when a calendar entry is activated (click or keyboard). The built-in <lms-menu> overlay listens for this internally.
| Property | Value |
|---|---|
| Source | <lms-calendar-entry> (bubbles through all view components via composed: true) |
| Bubbles | true |
| Composed | true |
| Detail | { heading: string, content: string, time: CalendarTimeInterval | undefined, displayTime: string, date: CalendarDate | undefined, anchorRect: DOMRect } |
You can intercept this event to show your own detail panel:
calendar.addEventListener('open-menu', (e) => {
e.stopPropagation(); // prevent built-in menu
showCustomPanel(e.detail);
});
Note: In month view,
<lms-calendar-month>re-dispatches this event to ensure it crosses the shadow boundary correctly.
menu-close
Fired when the built-in menu overlay is dismissed.
| Property | Value |
|---|---|
| Source | <lms-menu> |
| Bubbles | true |
| Composed | true |
| Detail | none |
calendar.addEventListener('menu-close', () => {
hideCustomSidebar();
});
peek-navigate
Fired in condensed week view when the user clicks the peek (arrow) buttons to slide the visible day window.
| Property | Value |
|---|---|
| Source | <lms-calendar-week> |
| Bubbles | true |
| Composed | true |
| Detail | { date: CalendarDate, direction: 'next' | 'previous' } |
calendar.addEventListener('peek-navigate', (e) => {
console.log('Peeked', e.detail.direction, 'to', e.detail.date);
});
Note: This event only fires when the week view is in condensed mode (fewer columns than 7, typically on mobile). The
datein the payload is the new target date.
locale-ready
Fired after a non-English locale's translation chunk has loaded and the component is ready to render with correct UI strings. English never fires this event (translations are built-in and always synchronous).
| Property | Value |
|---|---|
| Source | <lms-calendar> |
| Bubbles | true |
| Composed | true |
| Detail | { locale: string } |
Use this event (or the localeReady promise) to avoid showing the calendar before translations are loaded:
const calendar = document.querySelector('lms-calendar');
calendar.locale = 'de';
calendar.addEventListener('locale-ready', (e) => {
console.log(`${e.detail.locale} translations loaded`);
});
// Or use the promise-based API:
await calendar.localeReady;
Note: The component already hides its header and main content via
visibility: hiddenwhile loading, so consumers only need this event for custom coordination (e.g., showing a skeleton screen or deferring other work).
clear-other-selections (internal)
Fired when an entry receives focus, instructing the parent to clear all other selected entries. This is an internal coordination event — you generally should not need to listen for it.
| Property | Value |
|---|---|
| Source | <lms-calendar-entry> |
| Bubbles | true |
| Composed | true |
| Detail | { exceptEntry: HTMLElement } |
The parent <lms-calendar> listens for this and calls clearSelection() on all other entry elements. If you're building custom multi-selection UI, you may need to handle this.