Load events on demand as users navigate, and persist every change back to your server.
On this page
Instead of passing events up front, hand the scheduler a dataSource:
getEvents(start, end) runs whenever the visible range changes, and
persistEvents runs after every committed change.
new coreui.Scheduler(element, {
dataSource: {
getEvents: async (start, end) =>
(await fetch(`/api/events?from=${start}&to=${end}`)).json(),
persistEvents: async ({ action, event, occurrence, scope }) => {
const response = await fetch('/api/events', {
method: 'POST',
body: JSON.stringify({ action, event, occurrence, scope }),
})
return { success: response.ok } // success: false reverts the change
},
},
})Behavior
getEventsreceives the visible window as ISO strings (end exclusive) and fires on init and whenever navigation, view switches orupdate()change the range — never twice for the same range. A spinner (data-part="loading") shows while a request is in flight, and stale responses from superseded requests are discarded.- A failed load keeps the current events and announces the localizable
loadFailedmessage. persistEventsgets the same payload as theeventChangeDOM event (minusrevert). Returning{ success: false }— or throwing — reverts the change and announcessaveFailed. TheeventChangeevent still fires first, so analytics and optimistic UI keep working.getVisibleRange()returns the current window ({ start, end }) if you prefer wiring fetches yourself throughdateChange/viewChange.
Manual wiring
Everything above is also possible without dataSource — listen to
dateChange, fetch, call setEvents(), and call revert() from your
eventChange listener when the server rejects a change. dataSource is the
packaged version of exactly that pattern.