Examples
This page collects small, product-neutral Event Scheduler examples. The same APIs work for shifts, bookings, appointments, staffing, rooms, maintenance, tasks, equipment, and team planning.
The runnable demo catalog includes these complete scheduler stories:
| Demo | Use it for | | --- | --- | | Event Staff Scheduler | Resource timeline, coverage, conflicts, templates, saved views, and remote-mode controls. | | Employee Shift Planner | Week view with days on the x-axis, time on the y-axis, drag-create, move, resize, delete, and closed hours. | | Room Booking Scheduler | Resource booking with availability windows, blocked time, conflicts, and grouped resources. | | Equipment / Machine Scheduler | Maintenance planning, utilization, capacity rows, and exportable workload data. | | Developer Sprint Scheduler | Team/task planning, custom ranges, unassigned work, templates, and workload balancing. |
Basic weekly scheduler
Section titled “Basic weekly scheduler”import { EventSchedulerPlugin, type EventSchedulerConfig, type EventSchedulerEventEntity,} from '@revolist/revogrid-enterprise';
const events: EventSchedulerEventEntity[] = [ { id: 'booking-1', title: 'Customer onboarding', resourceId: 'room-a', startDateTime: '2026-06-08T09:00:00.000Z', endDateTime: '2026-06-08T11:00:00.000Z', type: 'booking', status: 'confirmed', },];
const eventScheduler: EventSchedulerConfig = { view: 'week', weekStartDate: '2026-06-08', weekStartsOn: 1, visibleDays: [1, 2, 3, 4, 5], timeRange: { start: '06:00', end: '22:00' }, slotMinutes: 30, locale: 'en-US', timeZone: 'UTC', editable: true, allowCreate: true, allowMove: true, allowResize: true, allowDelete: true, todayHighlight: true, showCurrentTimeMarker: true,};
grid.plugins = [EventSchedulerPlugin];grid.eventScheduler = eventScheduler;grid.eventSchedulerEvents = events;Custom event template
Section titled “Custom event template”grid.eventScheduler = { ...grid.eventScheduler, eventProperties: ({ event, isSelected, hasConflict, isLocked }) => ({ class: [ 'planner-event', isSelected ? 'planner-event--selected' : '', hasConflict ? 'planner-event--conflict' : '', isLocked ? 'planner-event--locked' : '', ].filter(Boolean).join(' '), style: { '--planner-event-accent': event.color ?? '#2563eb', }, }), eventContentTemplate: (h, { event, resource, start, end, isShortEvent }) => h('span', { class: 'planner-event__body' }, [ h('strong', { class: 'planner-event__title' }, event.title), isShortEvent ? null : h('span', { class: 'planner-event__time' }, `${start.slice(11, 16)}-${end.slice(11, 16)}`), resource ? h('small', { class: 'planner-event__resource' }, resource.name) : null, ]), eventTooltipTemplate: ({ event, resource, duration }) => `${event.title}\n${resource?.name ?? 'Unassigned'}\n${duration} minutes`,};Custom day header
Section titled “Custom day header”grid.eventScheduler = { ...grid.eventScheduler, dayHeaderFormatter: (date) => new Intl.DateTimeFormat('en-US', { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC', }).format(date), dayHeaderTemplate: (h, context) => h('span', { class: 'planner-day-header' }, [ h('strong', null, context.defaultLabel), context.today ? h('span', { class: 'planner-day-header__badge' }, 'Today') : null, context.holiday ? h('span', { class: 'planner-day-header__holiday' }, context.holidayLabel) : null, h('small', null, `${context.eventCount ?? 0} events`), ]), dayHeaderProperties: ({ today, weekend, holiday }) => ({ class: [ today ? 'planner-day-header--today' : '', weekend ? 'planner-day-header--weekend' : '', holiday ? 'planner-day-header--holiday' : '', ].filter(Boolean).join(' '), }),};Custom slot context menu
Section titled “Custom slot context menu”grid.eventScheduler = { ...grid.eventScheduler, contextMenu: { enabled: true, getSlotContextMenuItems: ({ slot }) => slot ? [ { id: 'create-booking', label: 'Create booking here', shortcut: 'C', action: () => createBooking(slot), }, { id: 'hold-slot', label: 'Block this time', group: 'availability', action: () => createHold(slot), }, ] : [], onContextMenuAction: ({ itemId, target, slot }) => analytics.track('scheduler_menu_action', { itemId, target, slot }), },};Custom current time marker
Section titled “Custom current time marker”grid.eventScheduler = { ...grid.eventScheduler, showCurrentTimeMarker: true, currentTimeUpdateInterval: 60_000, currentTimeLabelFormatter: ({ dateTime }) => new Intl.DateTimeFormat('en-US', { hour: 'numeric', minute: '2-digit', }).format(new Date(dateTime)), currentTimeMarkerProperties: ({ orientation }) => ({ class: `planner-now planner-now--${orientation}`, style: { '--event-scheduler-current-time-color': '#dc2626', }, }), currentTimeMarkerTemplate: (h, { label }) => h('span', { class: 'planner-now__label' }, label),};Closed hours and availability
Section titled “Closed hours and availability”grid.eventScheduler = { ...grid.eventScheduler, workingHours: { byDay: { 1: { start: '08:00', end: '18:00' }, 2: { start: '08:00', end: '18:00' }, 3: { start: '08:00', end: '18:00' }, 4: { start: '08:00', end: '18:00' }, 5: { start: '08:00', end: '16:00' }, 0: false, 6: false, }, }, closedHours: [ { id: 'lunch', days: [1, 2, 3, 4, 5], ranges: { start: '12:00', end: '13:00' }, title: 'Closed', reason: 'Lunch break', }, ], closedSlotTooltip: ({ title, reason }) => [title, reason].filter(Boolean).join(' - '), closedSlotTemplate: (h, { reason }) => h('span', { class: 'planner-slot__closed' }, reason ?? 'Closed'), isTimeSlotAvailable: ({ date, startMinutes }) => date !== '2026-06-19' && startMinutes >= 8 * 60,};Read-only mode
Section titled “Read-only mode”grid.eventScheduler = { ...grid.eventScheduler, editable: false, allowCreate: false, allowMove: false, allowResize: false, allowDelete: false, keyboardShortcuts: { enabled: true, shortcuts: { copy: 'Mod+c', paste: false, duplicate: false, delete: false, lock: false, }, },};Read-only mode keeps rendering, selection, tooltips, context menus, and custom templates active while blocking scheduler mutations.
Cancelable selection state
Section titled “Cancelable selection state”let selectedEventIds: readonly string[] = [];
grid.addEventListener('event-scheduler-before-event-select', (event) => { event.preventDefault(); selectedEventIds = event.detail.eventIds.map(String); renderScheduler();});
function renderScheduler() { grid.eventScheduler = { ...grid.eventScheduler, selectionMode: 'multiple', selection: { selectedEventIds, clipboard: true, onChange: ({ eventIds }) => { selectedEventIds = eventIds.map(String); renderScheduler(); }, }, onSelectionChange: ({ events }) => inspector.show(events), onEventMove: ({ events }) => { grid.eventSchedulerEvents = [...events]; void saveEvents(events); }, };}Use the before-select event when selection lives in application state. Prevent the pending scheduler selection, update host state, then pass the accepted ids back through selection.selectedEventIds. Event arrays, visible ranges, and filters follow the same ownership model: the scheduler emits callbacks and the host updates eventScheduler, eventSchedulerEvents, and related props.
Custom styling and theme
Section titled “Custom styling and theme”.booking-scheduler revo-grid { --event-scheduler-accent: #0f766e; --event-scheduler-accent-soft: #ccfbf1; --event-scheduler-grid-line: #d8dee6; --event-scheduler-current-time-color: #dc2626; --event-scheduler-weekend-bg: rgba(15, 118, 110, 0.05); --event-scheduler-event-bg: #eef7f3; --event-scheduler-event-color: #0f766e;}
.planner-event--conflict { --event-scheduler-event-color: #b45309; --event-scheduler-event-bg: #fff7ed;}
.planner-day-header--today { box-shadow: inset 0 -2px 0 var(--event-scheduler-accent);}Use CSS variables for broad theme changes. Use eventProperties, dayHeaderProperties, slotProperties, closedSlotProperties, and currentTimeMarkerProperties when styling depends on scheduler state.
Related guides
Section titled “Related guides”- Week View covers day/time configuration, visible range, week start, locale, timezone, and edit ownership.
- Customization documents the full visual customization category. Use Event Rendering for templates and tooltips, Slots, Hours, and Markers for slot and current-time examples, Context Menus for commands, and Styling and Themes for CSS hooks.
- Availability covers calendars, working hours, blocked time, breaks, holidays, and outside-hours styling.
- Editing and Interaction covers read-only mode, permissions, cancelable hooks, mutation events, selection, clipboard, keyboard shortcuts, custom editors, and persistence.