Skip to content

Calendar View

The calendar view renders an interactive calendar powered by FullCalendar. Events are embedded in the spec by the server — the UI displays them and optionally supports drag-drop rescheduling and date-click creation.

Preview
June 2026
Sun
Mon
Tue
Wed
Thu
Fri
Sat
31
1
2
3
Team standup
4
5
Release v2.0
6
8
9
10
11
Q2 Review
12
13
Spec
typescript
CalendarView.events(events)
  .defaultView('month')
  .title('Team Calendar')
  .build()

How it works

The SPA navigates to #/{resource}/calendar and fetches a CalendarSpec from GET /api/ui/{resource}/calendar. The spec includes all events pre-populated — no secondary fetches for initial render.

FullCalendar is initialized from the spec's events array and options. Subsequent interactions (clicking an event, dragging to reschedule) call your CRUD endpoints directly.

Basic setup (JS)

typescript
import { CalendarView } from '@retrofit-ui/builder-zod';

// URL prefix below is arbitrary — pick anything and match `apiBase` to it.
app.get('/schedule/events/calendar', async (_req, res) => {
  const events = await db.query(
    `SELECT id::text, title, start_at AS start, end_at AS end, color
     FROM events WHERE start_at >= NOW() - INTERVAL '30 days'`,
  );

  res.json(
    CalendarView.events(events)
      .defaultView('month')
      .title('Team Calendar')
      .build(),
  );
});

Event fields

FieldTypeRequiredDescription
idstringUnique identifier (must be a string)
titlestringEvent label shown on the calendar
startstringISO 8601 datetime or date string
endstringISO 8601 datetime or date string
colorstringCSS colour for this event's chip
allDaybooleanRenders as an all-day event when true
typescript
CalendarView.events([
  {
    id: '1',
    title: 'Team standup',
    start: '2026-06-15T09:00:00',
    end: '2026-06-15T09:30:00',
    color: '#3b82f6',
  },
  {
    id: '2',
    title: 'Company holiday',
    start: '2026-06-20',
    allDay: true,
    color: '#22c55e',
  },
]).build();

View modes

typescript
CalendarView.events(events)
  .defaultView('week')  // 'month' | 'week' | 'day' | 'list'
  .build();
ModeFullCalendar viewShows
'month' (default)dayGridMonthMonth grid
'week'timeGridWeek7-day time grid
'day'timeGridDaySingle-day time grid
'list'listWeekPlain list of upcoming events

Users can switch between all four views using the toolbar buttons.

CRUD endpoints

Configure endpoints to enable event interactions:

typescript
CalendarView.events(events)
  .find({ method: 'GET', url: '/events/{id}' })       // event click → navigate to detail form
  .create({ method: 'POST', url: '/events' })          // date click → navigate to new form
  .update({ method: 'PUT', url: '/events/{id}' })      // drag-drop / resize → API call
  .delete({ method: 'DELETE', url: '/events/{id}' })   // for use via the renderer
  .editable()
  .build();
EndpointTriggerBehaviour
findClick on an eventNavigates to #/{resource}/{id}
createClick on an empty dateNavigates to #/{resource}/new?start={date}
updateDrag-drop or resize an eventCalls the endpoint with { start, end } in the body; reverts if the request fails
delete(no UI trigger)Used by the renderer or custom integrations

editable() must be set alongside update to enable drag-drop and resize. Without it, events are read-only even if update is defined.

Editable calendar

Editable calendar
Editable mode enables two interactions:
  • Drag to reschedule — drops the event on a new date/time and PATCHes the server
  • Resize — drag the event's edge to change its end time
Both revert immediately if the API call fails.
Spec
typescript
CalendarView.events(events)
  .update({ method: 'PATCH', url: '/events/{id}' })
  .editable()
  .build();

Using the standalone renderer

html
<script src="retrofit-ui.iife.js"></script>

<!-- declarative island — auto-mounted by init() -->
<div data-retrofit-src="/specs/calendar.json"></div>

<!-- or mount explicitly in JS -->
<div id="cal" style="height: 600px;"></div>
<script>
  const ui = RetrofitUI.init({ rootElement: document.body, apiBase: '/api' });
  ui.mount(
    {
      kind: 'calendar',
      events: [
        { id: '1', title: 'Launch', start: '2026-07-01', color: '#3b82f6' },
      ],
      defaultView: 'month',
      metadata: { title: 'Product Roadmap' },
    },
    document.getElementById('cal'),
  );
</script>