# PDFViewer.on()

```ts
on<K extends keyof ViewerEventMap>(event: K, handler: (data: ViewerEventMap[K]) => void, options?: SubscribeOptions): () => void
```

Subscribe to a typed event. Document lifecycle events (`initialized`, `licenseChanged`, `documentLoaded`, `documentClosed`) are global and fire on `Kernstra.events`, not here; a handler registered on the wrong emitter never runs and never warns — see [EventEmitter](https://kernstra.com/docs/web-sdk/api/eventemitter).

- Kind: method
- Since: 1.0.0

| Parameter | Type | Description |
| --- | --- | --- |
| `event` | `keyof ViewerEventMap` | A per-viewer event name — see [Events](https://kernstra.com/docs/web-sdk/api/events). |
| `handler` | `(data: ViewerEventMap[K]) => void` | Receives the typed payload. |
| `options?` | `SubscribeOptions` | `once` hears the next emit only; `signal` unsubscribes when an `AbortSignal` aborts (a signal already aborted subscribes nothing). |

Returns `() => void`: The unsubscribe.

Throws:

- `INVALID_STATE` after `destroy()`.

```ts
const stop = viewer.on('pageChanged', ({ pageIndex }) => setCurrentPage(pageIndex));
stop();

const controller = new AbortController();
viewer.on('zoomChanged', ({ scale }) => setZoom(scale), { signal: controller.signal });
viewer.on('documentChanged', () => markDirty(), { signal: controller.signal });
controller.abort(); // both gone
```

Part of [PDFViewer](https://kernstra.com/docs/web-sdk/api/pdfviewer) in the Kernstra Web SDK 1.0.0 API reference.

Web page: https://kernstra.com/docs/web-sdk/api/pdfviewer/on
