Read-only Mode

Read-only mode disables the scheduler's built-in mutation UI: dragging, resizing, drag-to-create, and the edit controls in menus and panels. It is the right tool for public schedules, wallboards, and restricted user roles.

Programmatic APIs keep working

app.addEvent(), app.updateEvent(), app.deleteEvent(), and app.setEvents() are unaffected. Read-only controls what the user can do, not what your code can do.

Scope

Restrictions can be applied at three levels, from broadest to narrowest:

LevelSet withAffects
ApplicationreadOnly on the app configThe whole scheduler.
ResourcereadOnly on a ResourceEvery event on that row.
EventreadOnly on a SchedulerEventThat event only.

Application-wide

const app = useSchedulerApp({
  resources,
  events,
  readOnly: true,
});

Fine-grained Control

Pass a ReadOnlyConfig object to disable editing while keeping the schedule inspectable:

const app = useSchedulerApp({
  resources,
  events,
  readOnly: {
    draggable: false, // no moving or resizing
    viewable: true, // detail panel still opens
  },
});
OptionTypeDescription
draggablebooleanWhether events can be moved or resized by dragging.
viewablebooleanWhether event details can be opened.

When read-only is active, the scheduler also hides controls that would produce a change, for example "New event" in the grid context menu.

Per Resource

Lock a whole row while the rest of the schedule stays editable:

const resources = [
  { id: 'live', name: 'Live team' },
  { id: 'archive', name: 'Archive', readOnly: true },
];

Per Event

const events = [
  {
    id: 'frozen-release',
    title: 'Frozen release window',
    resourceId: 'live',
    start: '2026-04-16T09:00',
    end: '2026-04-16T10:00',
    readOnly: true,
  },
];

Custom UI

If you render your own buttons, menus, or dialogs, ask the app whether mutation controls should be shown rather than re-deriving the rules:

if (app.canMutateFromUI()) {
  // show create / edit / delete controls
}

if (app.canMutateFromUI('event-id-123')) {
  // this specific event is editable
}

canMutateFromUI() accounts for all three levels at once, so a globally editable scheduler still returns false for a locked event or a locked resource.

To read the effective configuration:

const { draggable, viewable } = app.getReadOnlyConfig('event-id-123');

Switching at Runtime

app.updateConfig({ readOnly: true });
app.updateConfig({ readOnly: false });

On this page