---
title: "Blok Events API — on, off, emit"
description: "Subscribe to editor events, emit your own, and the full list of events Blok itself dispatches."
source: https://blokeditor.com/docs/events-api/
lastmod: 2026-09-07
---

Framework JavaScript

Extending & system Events

On this page on(event, callback)

# Events API: subscribe to editor events

Subscribe to and manage editor lifecycle events.

[Edit this page on GitHub](https://github.com/JackUait/blok/blob/main/docs/src/components/api/api-data.ts)

### 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

### on(event, callback)

void

Subscribe to an editor event.

When to use

Subscribe to editor lifecycle/content events. Keep a reference to the same callback so you can `off()` it later.

TypeScript

```
// Listen for block mutations — the callback receives the event payload,
// not an API object
editor.on('block changed', ({ event }) => {
  console.log('Block mutated:', event.type);
});

// Listen for individual block renders
editor.on('block:rendered', ({ blockId }) => {
  console.log('Rendered block:', blockId);
});

// Wait for a container block's child holders to settle before touching them.
// A React/Vue/Angular block renders through a portal that commits AFTER
// block:rendered, so a caret set in that window is dropped; this event fires
// once the holders are in the container's slot (it repeats on every later
// reconciliation pass — it is a settle signal, not a change signal).
const child = editor.blocks.insertInsideParent(containerId);

editor.on('block:childrenMounted', ({ blockId, childIds }) => {
  if (blockId === containerId && childIds.includes(child.id)) {
    editor.caret.setToBlock(child.id);
  }
});

// With the `collaboration` config on, this is the sync/presence indicator
// feed: status is 'connecting' | 'connected' | 'offline' | 'error', and peers
// lists everyone else in the document. 'offline' is still retrying (retryInMs
// says when) and local edits stay pending; 'error' has stopped for good and
// carries the reason. Single-player editors never emit it.
editor.on('collaboration:status', ({ status, peers }) => {
  console.log(status, peers.map((peer) => peer.user.name));
});

// To react to content changes with access to the API, use the
// onChange(api, event) config callback (async is allowed there):
//   onChange: async (api) => { const data = await api.save(); }
```

### off(event, callback)

void

Unsubscribe from an editor event.

When to use

Pass the exact same function reference you subscribed with — anonymous inline callbacks can't be removed.

TypeScript

```
const handleRendered = (payload) => console.log('Rendered');
editor.on('block:rendered', handleRendered);

// Later, remove the listener (pass the same function reference)
editor.off('block:rendered', handleRendered);
```

### emit(event, data)

void

Emit a custom event. Fire-and-forget over the listeners registered at that moment — there is no replay, so a handler subscribed after the emit never sees it.

When to use

For tools/plugins to broadcast custom events on the editor bus; app code usually listens with `on()` rather than emits.

TypeScript

```
// Subscribe first — an emit with no listener is simply dropped
editor.on('custom-event', (data) => {
  console.log(data.message); // 'Hello'
});

editor.emit('custom-event', { message: 'Hello', data: 123 });
```
