PDF Generation Template Editor
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
Open-source visual PDF generation engine with customizable templates and developer-friendly APIs.
Use these APIs for annotation property panels, creation and selection events, and annotation undo/redo state.
| Callback or API | Parameters | Trigger |
|---|---|---|
onAnnotationStyleDialogDismissed | { type } | The annotation properties panel closes. |
reader._annotationsHistoryManager. | canUndo: boolean, canRedo: boolean | The annotation undo/redo state changes. |
CPDFReaderView supports multiple callbacks for the same CPDFEvent. Its public methods are:
addEventListener<K extends keyof CPDFEventDataMap>(
event: K,
callback: (eventData: CPDFEventDataMap[K]) => void,
): void;
removeEventListener<K extends keyof CPDFEventDataMap>(
event: K,
callback: (eventData: CPDFEventDataMap[K]) => void,
): void;| Event | Event data | Trigger |
|---|---|---|
CPDFEvent.ANNOTATIONS_CREATED | CPDFAnnotation | A non-form annotation is created. |
CPDFEvent.ANNOTATIONS_SELECTED | CPDFAnnotation | An annotation is selected. |
CPDFEvent.ANNOTATIONS_DESELECTED | CPDFAnnotation | null | An annotation is deselected. |
CPDFEvent.PENCIL_DRAWING_COMPLETED | { type: 'pencil'; pageIndex: number } | A Pencil drawing is saved (iOS only). |
CPDFEvent.PENCIL_DRAWING_DISCARDED | { type: 'pencil'; pageIndex: number } | A Pencil drawing is discarded (iOS only). |
The public TypeScript contract for annotation deselection is nullable; handle a null value before accessing the object. Pencil events are available only on iOS, and the returned pageIndex is zero-based.
These events cover creation and selection state. They do not provide annotation update or delete events, and they do not report save failures.
Register and remove the same stable function reference. Preserve the Reader instance used for registration because ref.current may already be null when an Effect cleanup runs.
const pdfReaderRef = useRef<CPDFReaderView | null>(null);
const subscribedReaderRef = useRef<CPDFReaderView | null>(null);
const onAnnotationCreated = useCallback((annotation: CPDFAnnotation) => {
console.log('Created annotation:', annotation.type);
}, []);
const onViewCreated = useCallback(() => {
const reader = pdfReaderRef.current;
if (!reader || subscribedReaderRef.current === reader) {
return;
}
subscribedReaderRef.current = reader;
reader.addEventListener(
CPDFEvent.ANNOTATIONS_CREATED,
onAnnotationCreated,
);
}, [onAnnotationCreated]);
useEffect(() => {
return () => {
const reader = subscribedReaderRef.current;
if (!reader) {
return;
}
reader.removeEventListener(
CPDFEvent.ANNOTATIONS_CREATED,
onAnnotationCreated,
);
subscribedReaderRef.current = null;
};
}, [onAnnotationCreated]);removeEventListener() returns void. RN does not provide removeAllEventListeners() and does not stop native event generation when the last JavaScript listener is removed. The local Listener Map is released with the Reader instance; explicit removal is most important when an Effect reruns or the Reader remains mounted.