How to render xfdf back into pdf

Hello rakshitha_r,

The ‘documentLoaded’ event only triggers when loading a document, as such, you would want to use it under a different event i.e. ‘annotationsLoaded’ event Add Events to Annotations with PDF.js Express | Documentation

This is a sample code of using a sample xfdfString of a rectangle annotation:

  const { documentViewer, annotationManager } = instance.Core;

  documentViewer.addEventListener('annotationsLoaded', async () => {
    console.log('annotations loaded, removing all annotations');
    const annotationsList = annotationManager.getAnnotationsList();
    annotationManager.deleteAnnotations(annotationsList);
  });
  
  document.getElementById('sample-button').addEventListener('click', async (e) => {
    const xfdfString = `<?xml version="1.0" encoding="UTF-8" ?><xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve"><pdf-info xmlns="http://www.pdftron.com/pdfinfo" version="2" import-version="4" /><fields /><annots><square page="0" rect="75.420,517.250,276.090,673.480" color="#E44234" flags="print" name="2bdc9ec3-5f5f-9957-fc14-29bfdf924e89" title="Guest" subject="Rectangle" date="D:20220914102039-07'00'" opacity="0.8530899712330127" creationdate="D:20220914102039-07'00'"/></annots><pages><defmtx matrix="1,0,0,-1,0,792" /></pages></xfdf>`;
    console.log('before import', annotationManager.getAnnotationsList());
    await annotationManager.importAnnotations(xfdfString);
    console.log('after import', annotationManager.getAnnotationsList());
  })

Let me know if that works for you.

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

hi Kevin,
thanks for response.
Kevin, my requirement is that, when i add an annotation, i am capturing and storing that out of WebViewer, when i am going to click on checkbox which has no connection to webViewer but i will have that xfdfString data, so it is like i have to make dummy event call inside webViewer and make my xfdfString to show annotation on webViewer.
this line is giving me error as well,
document.getElementById Object is possibly ‘null’.

thanks

Kevin, by modify based on my requirement i am now able to show annotation on the webviewer, but when i have multiple pages, based on my checkbox check, i am able to get annotation box, but now i am in page1, but the checkbox i selected has annotation in second page or in end of the page means, it still remains in top section of page, and doesnt page scroll to show particular annotated box., but in my xml string i am able to see page number as 1 or 0.

this set of code is importing the annotation on pdf perfectly, but it is not scrolling to that particular row or page, it remains where user has scrolled manually but annotation will be drawn, when user manually scrolls, then we will be able to see.

this.setAnnotationEvent.subscribe(() => {
const xfdfString = this.renderingInstance;
annotationManager.importAnnotations(xfdfString);
this.renderingInstance = ‘’;
});

what changes should i do here, so that page scrolls and shows me annotation.
thanks

Kevin, for removing particular annotation based on checkbox uncheck, i am using this set of code,

this.removeAnnotationEvent.subscribe(() => {
const annotationsList = annotationManager.getAnnotationsList();
annotationManager.deleteAnnotation(this.renderingInstance);
});
where this.renderingInstance is <?xml version="1.0" encoding="UTF-8" ?><xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve"><pdf-info xmlns="http://www.pdftron.com/pdfinfo" version="2" import-version="4" /><fields /><annots><square page="0" rect="75.420,517.250,276.090,673.480" color="#E44234" flags="print" name="2bdc9ec3-5f5f-9957-fc14-29bfdf924e89" title="Guest" subject="Rectangle" date="D:20220914102039-07'00'" opacity="0.8530899712330127" creationdate="D:20220914102039-07'00'"/></annots><pages><defmtx matrix="1,0,0,-1,0,792" /></pages></xfdf>;

Hello rakshitha_r,

If you want to attach an event to the import of the annotation and make an autoscroll to that annotation, you can do something like this:

  annotationManager.addEventListener('annotationChanged', (annotations, action, {imported}) => {
    if (imported) {
      console.log('imported annotation', annotations[0])
      documentViewer.setCurrentPage(annotations[0].PageNumber);
    }
  });

Here is a reference guide for the above API:

https://pdfjs.express/api/Core.DocumentViewer.html#setCurrentPage

For deleting annotations, you would want to reference the actual Annotation object itself rather than the XML data:
https://pdfjs.express/api/Core.AnnotationManager.html#deleteAnnotation__anchor

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

thanks for response Kevin,
for example i made 2 annotations, one at first row section of page and other one at last row section of page, but when i want to import that annotation based on selection of checkbox, it stays at first page top, but doesnt show that last row, is there anyway where in we can show that particular section when clicked.

Hello rakshitha_r,

If I am understanding correctly, you would like to jump to a particular section based on the imported annotation’s location.

Since the XFDF data from the annotation contains the coordinates, you can use the displayPageLocation API: PDFJS Express WebViewer Class: DocumentViewer
and do something like this:

annotationManager.addEventListener(‘annotationChanged’, (annotations, action, {imported}) => {
if (imported) {
console.log(‘imported annotation’, annotations[0])
documentViewer.displayPageLocation(annotations[0].PageNumber, annotations[0].X, annotations[0].Y);
}
});

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

thanks Kevin, your solution made my day, currently i am looking for deleting selected annotation by converting to actual object.
i searched and i tried by saving the actual annotation and passing same annotation when i need to delete so that actual annotation will be present but i failed in this as well.
any example? it would really help me

Hello rakshitha_r,

Glad that worked out for you.

You can use the AnnotationManager to select a particular annotation and then pass that to the deleteAnnotation.

For example, if you create an annotation and select it, you can type this into the console:


And this will delete the selected annotation

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

sure i will check this and update you .

i tried but i am getting error like this, documentViewer.getAnnotationsList is not a function.


const annotationManager = documentViewer.getAnnotationsList();
 const selectedAnnotation = annotationManager.getSelectedAnnotations()[0];
 annotationManager.deleteAnnotations(selectedAnnotation);

Hello rakshitha_r,

You will need to change the layer in the dev-tools from ‘top’ to ‘webviewer-1’ to be in the context of WebViewer:
image

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

got it Kevin i will try now, i have changed in developer console and tried but still get same issue, even in application also same issue. here i should be able to select checkbox show annotation on PDF, when unchecked remove annotation from pdf, so multiple annotations can be added/removed based on selection of checkbox.
here, deleting all annotations at one time works fine with this code,

const annotationsList = annotationManager.getAnnotationsList();
annotationManager.deleteAnnotations(annotationsList);

but deleting individual annotation based on uncheck is failing.
i even tried with this,

const annotationlist = annotationManager.getAnnotationsList();
let xfdfString = `<?xml version="1.0" encoding="UTF-8" ?><xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve"><pdf-info xmlns="http://www.pdftron.com/pdfinfo" version="2" import-version="4" /><fields /><annots><square page="0" rect="75.420,517.250,276.090,673.480" color="#E44234" flags="print" name="2bdc9ec3-5f5f-9957-fc14-29bfdf924e89" title="Guest" subject="Rectangle" date="D:20220914102039-07'00'" opacity="0.8530899712330127" creationdate="D:20220914102039-07'00'"/></annots><pages><defmtx matrix="1,0,0,-1,0,792" /></pages></xfdf>`
const index: number = this.annotationList.indexOf(xfdfString);
annotationManager.deleteAnnotations(selectedAnnotation);

failed here as well.

Hello rakshitha_r,

For deleting individual annotation you will need to use deleteAnnotation:
https://pdfjs.express/api/Core.AnnotationManager.html#deleteAnnotation

For deleting an array of annotations, you will need to use deleteAnnotations:
https://pdfjs.express/api/Core.AnnotationManager.html#deleteAnnotations

One thing to note is that once you imported the xfdfString after calling importAnnotations, you will no longer need to reference it by the xfdfString but rather the annotation that was imported.

So in this case, after you import and have an event that triggers when importing, you have the annotation properties:

annotationManager.addEventListener(‘annotationChanged’, (annotations, action, {imported}) => {
  if (imported) {
    console.log(‘imported annotation’, annotations[0])
    documentViewer.displayPageLocation(annotations[0].PageNumber, annotations[0].X, annotations[0].Y);

// if you want to delete this annotation that was just imported, you can use 
// annotationManager.deleteAnnotation(annotations[0])
}
});

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

hi Kevin,
i need to delete annotation which is already present on pdf, based on checkbox uncheck i need to delete one particular annotation which is already present.
i will try and keep you posted.

thanks a lot for your support Kevin, as my requirement was quite different, so i saved the creationdate of annotation at time of export and by comparing that date with list of getAnnotations i was able to compare and delete the particular annotation.
your each message help me to fix my issues.
Thanks again

hi Kevin,
i am now struck with 2 more things, can i ask my clarifications here or do i need to create new topic?

i have got around 8 annotations drawn across 3 pages of pdf and stored in a variable, when i choose selectAll, there is missing annotations in 1st page sometimes, 2nd page sometimes, i am not sure for what reason this issue is arising, when i select individual checkbox, i get annotation draw perfectly, but when i checkfor all annotations at a time, it is getting missed from getting drawn, but i am able to get 8 times detection, i mean all 8 items are going in list.

  selectAllAnnotations() {
    for (let i = 0; i < storedAnnotationList.length; i++) {
      setTimeout(() => {
        this.setAnnotation(this.storedAnnotationList[i]);
      });
    }
  }

  setAnnotation(event: any) {
    this.renderingInstance = event.annotationString;
    this.setAnnotationEvent.emit();
  }

    this.setAnnotationEvent.subscribe(() => {
        const annotationsList = annotationManager.getAnnotationsList();
        const xfdfString = this.renderingInstance;
        annotationManager.importAnnotations(xfdfString);
        this.renderingInstance = '';
      });

this method is called inside WebViewer

this.setAnnotationEvent.subscribe(() => {
        const annotationsList = annotationManager.getAnnotationsList();
        const xfdfString = this.renderingInstance;
        annotationManager.importAnnotations(xfdfString);
        this.renderingInstance = '';
      });

so when i choose on selectAll, selectAllAnnotations() method hits and here, i am calling setAnnotation() method, so object by object, the annotations are going and getting added to pdf with this.setAnnotationEvent. last set of code.
am i wrong here?
thanks

Hello rakshitha_r,

From what I understand, you are trying to select all 8 annotations across 3 pages of the PDF. Sometimes when you select those annotations, it is missing the annotations you just ‘drawn/imported’ (from the xfdf)

What is happening is that before you work with the entire list of annotations you have 2 references to the annotationsList: before & after importAnnotations method.

After calling importAnnotations, you can make sure that the annotations are imported by checking annotationManager.getAnnotationsList() then select the annotations. (I think your storedAnnotationList might not be updated)

Also, feel free to create a new forum post if the original topic has been resolved.

Best Regards,
Kevin Kim
Web Development Support Engineer
PDFTron Systems, Inc.


Share how you are using PDF.js Express in your organization you could win a $500 Amazon gift card. All participants will receive 6 months of PDF.js Express+ for free. Learn more here

Kevin, here as i am binding 8 annotations, based on index from list of annotations, so its like when checkbox is checked, i am taking that array list and passing individual annotation string in a loop and binding, so for this do we have any solution?