Skip to content
FrameworkJavaScript

Read-only API: toggle editing on and off

Control the read-only state of the editor. Toggling happens in place as long as every registered block tool implements setReadOnly(state) on its prototype. Every bundled tool does.

The same editor instance then flips modes and keeps caret position, undo history and scroll. So an edit/view toggle is readOnly.set(!isEditing) on ONE instance, instead of destroying one editor and constructing another.

The check is all-or-nothing. Install a single block tool without setReadOnly and every toggle falls back to a save, clear and re-render cycle. That cycle recreates all block instances and does not restore the caret. Scroll is still restored, and the undo history is deliberately left untouched.

Last updated Sep 8, 2026Edit this page on GitHub

Reaching the editor instance

The methods below run on the editor you created with new Blok(). They are available once editor.isReady resolves.

TypeScript
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;

// Call any API method on it.
editor.caret.setToLastBlock('end');

Methods

readOnly.set(state, options?)

Promise<boolean>

Set read-only mode to the specified boolean state. The toggle happens in place, with no destroy or recreate step: block instances, caret position, undo history and scroll are all preserved.

That holds only if every registered block tool implements setReadOnly(state) on its prototype. The check is all-or-nothing.

One tool without it sends EVERY toggle down the fallback path of save, clear and re-render (every bundled tool has one, a third-party tool may not). That path recreates all block instances and does not restore the caret, though scroll and undo history still survive.

Pass { hideControls: true } to also hide the hover toolbar, block settings and inline toolbar while read-only is active. The option writes the object form of config.readOnly, so the live state reflects it. Returns the new state.

When to use

The preferred way to enter or leave read-only mode. It toggles in place and preserves caret, undo history and scroll, as long as every registered block tool implements setReadOnly(). Returns a promise that resolves to the new state once applied.

Parameters

ParameterTypeRequiredDefaultDescription
statebooleanRequired—

Read-only state to set.

options.hideControlsboolean—unchanged (inherits the current `config.readOnly`)

Hide all editor controls (hover toolbar, block settings popover, inline toolbar) while read-only is active.

The value is sticky. set() writes config.readOnly only when you pass an actual boolean, so omitting the option keeps whatever hideControls is already in effect, from the constructor config or from an earlier set() call.

Pass { hideControls: false } explicitly to bring the controls back. false is the effective value only when config.readOnly was never given in object form.

TypeScript
// The edit/view toggle: ONE instance, flipped in place —
// caret, undo history and scroll survive the switch
await editor.readOnly.set(!isEditing);

// Enable read-only and hide all controls
// (hover toolbar, block settings, inline toolbar)
await editor.readOnly.set(true, { hideControls: true });

// Check state
console.log(editor.readOnly.isEnabled); // true or false
console.log(editor.readOnly.togglesInPlace); // true

readOnly.toggle(state?)

Promise<boolean>Deprecated

Toggle read-only state. Without a parameter it toggles the current state. With a parameter it sets the specified state.

Use instead: readOnly.set

When to use

Kept for compatibility. It flips the current state when called without a parameter.

TypeScript
// Toggle current state
const isReadOnly = await editor.readOnly.toggle();

// Enable read-only
await editor.readOnly.toggle(true);

// Disable read-only
await editor.readOnly.toggle(false);

Properties

PropertyTypeDescription
isEnabledboolean

Current read-only state

togglesInPlacetrue

A build-level marker, hardcoded to true. It says this build of Blok has the in place toggle path, instead of always recreating the editor.

It is not a capability probe. It does not report whether the currently installed tool set qualifies for that path. That path needs every block tool to implement setReadOnly, and it is not exposed anywhere.

Use the marker only to detect a Blok build old enough to predate in-place toggling.

TypeScript
// The edit/view toggle: one instance, one call.
// Caret, undo history and scroll survive the switch —
// no destroy-and-recreate.
async function setEditing(isEditing: boolean) {
  await editor.readOnly.set(!isEditing);
}

// Framework adapters do this for you: change the readOnly
// prop (React/Vue) or input (Angular) and the adapter calls
// readOnly.set on the existing instance — same editor identity.