Semantic Compare show annotations for the second document

Looks like in your code, you’re also using the document1AnnotationManager for the 2nd document. Could it be the issue?

this.saveAnnotations(document1AnnotationManager, annotations, action);
1 Like

Good catch. I noticed that version 10.2.3 has been released, so I switched to that. I have fixed my example code based on what you found, but I’m still seeing the main problem that I am having in my production code. When adding comments to the document on the right, the event for document viewer 1 is firing, and the XFDF data is missing. Everything else appears to be correct (the initial add of the annotation, replies and deleting).

import { AfterViewInit, Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core';
import WebViewer, { Core, WebViewerInstance } from "@pdftron/webviewer";
import { Subject } from "rxjs";

@Component({
  selector: 'app-root',
  styleUrls: ['app.component.css'],
  templateUrl: 'app.component.html'
})
export class AppComponent implements AfterViewInit {
  wvInstance?: WebViewerInstance;

  @ViewChild('viewer') viewer!: ElementRef;

  @Output() coreControlsEvent: EventEmitter<string> = new EventEmitter();

  private documentLoaded$: Subject<void>;

  constructor() {
    this.documentLoaded$ = new Subject<void>();
  }

  ngAfterViewInit(): void {

    WebViewer({
      path: '../lib',
      fullAPI: true
    }, this.viewer.nativeElement).then(instance => {
      this.wvInstance = instance;

      const { documentViewer, Annotations, annotationManager } = instance.Core;

      instance.UI.openElements(['notesPanel']);

      documentViewer.addEventListener('annotationsLoaded', () => {
        console.log('annotations loaded');
      });

      const { UI, Core } = instance;
      const { Color } = Annotations;

      UI.addEventListener(UI.Events.MULTI_VIEWER_READY, () => {
        const [documentViewer1, documentViewer2] = Core.getDocumentViewers();
        const startCompare = async () => {
          const shouldCompare = documentViewer1.getDocument() && documentViewer2.getDocument();
          if (shouldCompare) { // Check if both documents loaded before comparing
            const beforeColor = new Color(21, 205, 131, 0.4);
            const afterColor = new Color(255, 73, 73, 0.4);
            const options = { beforeColor, afterColor };
            await documentViewer1.startSemanticDiff(documentViewer2, options);
          }
        }
        documentViewer1.addEventListener('documentLoaded', startCompare);
        documentViewer2.addEventListener('documentLoaded', startCompare);
        documentViewer1.loadDocument('http://localhost:4200/files/fluffy.pdf');
        documentViewer2.loadDocument('http://localhost:4200/files/scooby.pdf');

        let document1AnnotationManager = documentViewer1.getAnnotationManager();
        document1AnnotationManager.addEventListener(
          'annotationChanged',
          (annotations: any, action: any, { imported }: any) => {
            console.log('AnnotationManager 1 ------------ annotationChanged');
            this.saveAnnotations(document1AnnotationManager, annotations, action);
          }
        );


        let document2AnnotationManager = documentViewer2.getAnnotationManager();
        document2AnnotationManager.addEventListener(
          'annotationChanged',
          (annotations: any, action: any, { imported }: any) => {
            console.log('AnnotationManager 2 ----------- annotationChanged');
            this.saveAnnotations(document2AnnotationManager, annotations, action);
          }
        );
      });
      UI.enableFeatures([UI.Feature.MultiViewerMode]);
    })
  }

  private saveAnnotations(annotationManager: Core.AnnotationManager,
    annotations: any,
    action: string) {

    annotations.forEach((annotation: Core.Annotations.Annotation) => {
      annotationManager.exportAnnotationCommand().then((xfdfData: any) => {
        console.log(`Saving... ${action}`);
        console.log(`XFDF data = ${xfdfData}`);
      });
    });
  }

}

Annotations-not-saving-comments-document-2

1 Like

Hi,

I was able to reproduce the issue. I have added the bug to our back log and it will be reviewed later.

Thanks.

2 Likes

Thank you for your good solution.
i need help to dynamic file name.

I have following code

UI.addEventListener(UI.Events.MULTI_VIEWER_READY, () => {
  const [documentViewer1, documentViewer2] = Core.getDocumentViewers();
  const startCompare = async () => {
    const shouldCompare = documentViewer1.getDocument() && documentViewer2.getDocument();
    if (shouldCompare) { // Check if both documents loaded before comparing
      const beforeColor = new Color(21, 205, 131, 0.4);
      const afterColor = new Color(255, 73, 73, 0.4);
      const options = { beforeColor, afterColor };
      const { doc1Annotations, doc2Annotations, diffCount } = await documentViewer1.startSemanticDiff(documentViewer2, options);
    }
  }

  const docLoaded1 = async () => {
  console.log(documentViewer1)
  console.log(documentViewer2)
  documentViewer2.loadDocument( url_par_d2, {loadAsPDF: true, extension: 'pdf', filename: 'Dokument 2' });
  }

  documentViewer1.addEventListener('documentLoaded', docLoaded1);
  documentViewer2.addEventListener('documentLoaded', startCompare);

documentViewer1.loadDocument( url_par_d1, {loadAsPDF: true, extension: 'pdf', filename: 'Dokument 1' });

});

In this code I write statically the name of the documents (“Document 1” and “Document 2”) but I want to show the name of the document dynamically, can you help me?

1 Like

Hi William,

The fix should be available in the latest nightly build of WebViewer v10.3, please try it out.

2 Likes

Can you use the variables url_par_d1 and url_par_d2? For my real codebase, the urls to load the files do not contain a user friendly name. Instead, our API to get the information for the files to be compared also contains a nicer name. I then use this function to create the object passed into the documentViewer.loadDocument() function:

private getFilenameObjectByFilenameAndExtension(filename: string | undefined, extension: string | undefined): any {
    if (!filename || !extension) {
      return {};
    }

    return { filename: `${filename}.${extension}` };
  }
1 Like