Add and save annotation to specific pages (only the last created annot is persisting)

WebViewer Version: latest

I’ve got an API which stores pages and their annotations. So in my case, annotations belongs to pages. So the API is serving pages and their annotations.
The API can serve different pages which are assembled on-the-fly to generate a “document” which is given to the PDFTron DocumentViewer.

That being said, here’s the code I’m using for loading existing annotations into the document’s right page, and for saving if any annotation has been added / edited or deleted :

// load annnotations
documentViewer.addEventListener(customEvent.LOAD_ANNOTATION, async ({ annotations }) => {

    // I'm using WebViewer in different places of my app and I didn't need Annotations loading everywhere
    if (enableAnnots && annotations?.length) {
        const annots = await annotationManager.importAnnotCommand(annotations);
        annots.forEach((a) => {
            annotationManager.redrawAnnotation(a);
        });
    }
});

// Manual annotation changed
annotationManager.on('annotationChanged', async (annotations, action, { imported }) => {
    // If the event is triggered by importing then it can be ignored
    if (imported) return;

    await documentViewer.getAnnotationsLoadedPromise();

    const xfdfString = await annotationManager.exportAnnotationCommand();

    // Send annotation change event for saving annotations to the right page in the API
    onChangeAnnotation?.({ xfdfString, pageNum: documentViewer.getCurrentPage() });
});

The annotations loading works well.

But each time I’m adding an annotation on a page, it automatically erases all existing annotations on this page. I took a look at the annotationChanged annotations array, and it always contains the only annotation I just created, not the ones that previously existed.

So please can you tell me how to get all the annotations of the current page when an annotations has been added, modified or deleted OR how the get the whole annotations array in order to keep the existing ones and send the right XFDF string to the API?

Cheers!

Hello @m.lafarie,

Looking at the code below:

annotationManager.on('annotationChanged', async (annotations, action, { imported }) => {
    // If the event is triggered by importing then it can be ignored
    if (imported) return;

    await documentViewer.getAnnotationsLoadedPromise();

    const xfdfString = await annotationManager.exportAnnotationCommand();

    // Send annotation change event for saving annotations to the right page in the API
    onChangeAnnotation?.({ xfdfString, pageNum: documentViewer.getCurrentPage() });
});

Is there a reason you are using the exportAnnotationCommand method? As per the docs this method returns:

Gets an XML string from the last time this function was called.

As you noticed, the event listener for annotationsChanged will only fire with the annotations that were actually affected by the change.

So please can you tell me how to get all the annotations of the current page when an annotations has been added, modified or deleted OR how the get the whole annotations array in order to keep the existing ones and send the right XFDF string to the API?

To do this you can simply get all the annotations from the document, then filter the ones for the page you want, and then export those annotations. Here is an example:

 async function getAnnotationsFromCurrentPage() {
    const annotations = annotationManager.getAnnotationsList().filter(annotation => annotation.PageNumber === documentViewer.getCurrentPage());
    const annotationsXFDF = await annotationManager.exportAnnotations({ annotList: annotations });
    return annotationsXFDF;
  }

And some methods you can leverage:
exportAnnotations
getAnnotationsList

Let me know if that helps.

Best Regards,
Armando Bollain
Software Developer
PDFTron Systems, Inc.