Skip to content
ComPDF
New Release

Open-Source PDF SDK & AI Document Processing

Get the full self-hosted SDK and AI document processing on GitHub. One-click deploy to quickly build your document workflows.

Events

The ComPDFKit engine uses a custom EventBus for cross-module communication. The UI layer listens to engine events to keep its state in sync and exposes addEvent / removeEvent so integrators can react to the same events.

The EventBus

The engine's EventBus is exposed through the core bridge:

javascript
instance.Core.eventBus();   // the engine's event bus
instance.Core.addEvent(name, handler);
instance.Core.removeEvent(name, handler);

eventBus.js in the bridge is a thin accessor — it returns core.getDocumentViewer().eventBus, exposing the engine's own bus. It holds no state of its own.

Common engine events

EventFires when
annotationSelected / annotationDeselectedAn annotation is selected / deselected.
annotationChangedAnnotations are added/modified/deleted.
toolChangedThe active tool changes.
toolModeChangedThe tool mode changes.
scalechangingThe zoom scale changes.
pagerenderedA page finishes rendering.
documentloadedThe document finishes loading.
onPagesUpdatedPages are updated (syncs outlines, page count, current page, scale, scroll/spread mode).
openAnnotationReplyAn annotation reply thread is opened.
updateAnnotationPermissionAnnotation permissions change.
contentEditHistoryChanged / historyChangedContent-edit / general history changes (drives undo/redo flags).
changeRightPanelBtnDisabledRight-panel button disabled state changes.
presentationmodechangedPresentation mode toggles.

How the UI listens

Components register listeners in their setup/mount lifecycle. For example, DocumentContainer.vue registers updateAnnotationPermission, toolModeChanged, toolChanged, annotationSelected/annotationDeselected, openAnnotationReply, onPagesUpdated, annotationChanged, and documentloaded during initViewer().

The createHeaderItemsListener (in components/HeaderItems/HeaderItemsListener.js) watches activeTool and selectedAnnotation to recompute the four property-panel button disabled flags and subscribes to annotationSelected, annotationDeselected, changeRightPanelBtnDisabled, and presentationmodechanged.

useHistoryListener bridges contentEditHistoryChanged / historyChanged into useDocument.setCanUndo / setCanRedo.

Lifecycle note: helpers/hooks/useOnAnnotationPopupOpen.js registers annotationSelected / annotationDeselected and removes them via onScopeDispose, so listeners are cleaned up when the owning scope (component setup or effectScope) disposes. When registering listeners yourself through core.addEvent, mirror this by removing them in onUnmounted (or onScopeDispose) to avoid leaks.

Examples

Listen for document load

javascript
instance.Core.addEvent('documentloaded', () => {
  console.log('Document loaded');
});

Listen for annotation changes

javascript
const handler = (annotations, type) => {
  console.log('annotations', type, annotations);
};
instance.Core.addEvent('annotationChanged', handler);
// later
instance.Core.removeEvent('annotationChanged', handler);

Listen for tool changes

javascript
instance.Core.addEvent('toolChanged', (toolName) => {
  console.log('Active tool:', toolName);
});

The viewer-loaded handshake

Beyond engine events, the iframe↔parent handshake uses postMessage:

  1. The iframe posts { type: 'viewerLoaded', docId } to window.parent when the UI is ready (App/index.vue onMounted).
  2. webviewer.js listens for it, captures iframe.contentWindow.instance, fires a ready CustomEvent on the host element, and posts { type: 'viewerLoaded', options } back into the iframe.

Integrators can listen for the ready event on the host element, or simply await ComPDFKitViewer.init(...) which resolves with instance once ready.