How to view PDF using Adobe EMbed Api in Angular with Text Selection and Annotation?

Vikas Kohli
6 min readOct 28, 2020

For Using the Adobe EMbed API, we need to create an account in the adobe as in the embed API, there is a client id and if we need to deploy the code in the server then we must have the client id registered to that domain. If not then we not able to use the Adobe Embed APIs.

Also, this library is available in the React and Angular along with the samples which make Angular and React developers easy to integrate the Adobe Embed API.

Let’s integrate into Angular.

In index.html, we need to import the adobe SDK js file

<script type='text/javascript' src='https://documentcloud.adobe.com/view-sdk/main.js'></script>

Also for the SDK service, we will create a file view-sdk-service file

import { Injectable } from '@angular/core';
declare global { interface Window { AdobeDC: any; } }

Here they add AdobeDc in the Window config, but in the typescript, we can’t use directly so we declare an interface that AdobeDc property exists in the window object.

@Injectable({
providedIn: 'root'
})
export class ViewSDKClient {
readyPromise: Promise<any> = new Promise((resolve) => {
if (window.AdobeDC) {
resolve();
} else {
/* Wait for Adobe Document Services PDF Embed API to be ready */
document.addEventListener('adobe_dc_view_sdk.ready', () => {
resolve();
});
}
});
adobeDCView: any;
ready() {
return this.readyPromise;
}
previewFile(divId: string, viewerConfig: any, fileName: string){
const config: any = {
/* Pass your registered client id */
clientId: "my client id get from adobe" // we can import from environment file
};
if (divId) { /* Optional only for Light Box embed mode */
/* Pass the div id in which PDF should be rendered */
config.divId = divId;
}
/* Initialize the AdobeDC View object */
this.adobeDCView = new window.AdobeDC.View(config);
/* Invoke the file preview API on Adobe DC View object */
const previewFilePromise = this.pdfRef = this.adobeDCView.previewFile({
/* Pass information on how to access the file */
content: {
/* Location of file where it is hosted */
location: {
url: fileName, // pdf file,
/*
If the file URL requires some additional headers, then it can be passed as follows:-
headers: [
{
key: '<HEADER_KEY>',
value: '<HEADER_VALUE>',
}
]
*/
},
},
/* Pass meta data of file */
metaData: {
/* file name */
fileName: 'my file.pdf',
/* file ID */
id: 'mmy file id'
}
}, viewerConfig);
}}

let’s create a pdf component.

In pdf.component.html

<input type="text" [(ngModel)]="pdfURL" /> <button (click)="renderPDf2()">Render PDF</button>
<div id='pdf-div' style="display:none" class='pdf-view'></div>

Initially, we set a div display to none and create an input field where the user enters the pdf URL and then click on the render button.

In pdf.component.css, we set the border and their height and width.

.pdf-view {
margin: auto;
margin-top: 5%;
height: 90vh;
width: 900px;
border: 1px solid #dadada;
}

In pdf.component.ts

import { ViewSDKClient } from '../shared/services/view-sdk.service';export class PDFComponent implements OnInit {
constructor(
private viewSDKClient: ViewSDKClient
) {
}
renderPDf(){
this.viewSDKClient.ready().then(() => {
/* Invoke file preview */
const canvas: any = this.document.querySelector('#pdf-div');
canvas.style.display = "block";
let defConfg = {
// defaultViewMode: "FIT_WIDTH"
}
this.viewSDKClient.previewFile('pdf-div',defConfg,this.pdfURL,);
});
}

In the above, we pass the pdf URL to view-sdk.service, and then using adobe SDK, pdf is loaded.

Pdf rendered

When left navigation set to true, then it will show an icon of the page, when you click on it it will generate thumbnails of each page and we navigate to the page by directly clicking on the thumbnail.

Pdf with left navigation enabled

When we click on the there dots on the right side of the toolbar, it will show the following options:-

Pdf other options

Legal Notices will appear every time but we control the download and print pdf option.

The following properties in that default configuration object of adobe embed API as mentioned below:-

enableAnnotationAPIs, showLeftHandPanel, showPrintPDF, includePDFAnnotations, showAnnotationTools, defaultViewMode, showPageControls

For listening annotation, like when annotation added, updated, deleted, we need to enable annotation Api first and then add listener, so we will modify the view-sdk.service file

annotList: any = [];pdfRef: any;previewFile(divId: string, viewerConfig: any, fileName: string, list_of_annotations?: any) {
const eventOptions = {
// Pass the events to receive.
// If no event is passed in listenOn, then all the annotation events will be received.
listenOn: [
"ANNOTATION_ADDED", "ANNOTATION_CLICKED", "ANNOTATION_UPDATED", "ANNOTATION_DELETED"
]
}
const customFlags = {
showToolbar: true,
showCommentsPanel: true,
downloadWithAnnotations: true,
showToolsOnTextSelection: true,
printWithAnnotations: true
}
const config: any = {
/* Pass your registered client id */
clientId: "my adobe client id"
};
if (divId) { /* Optional only for Light Box embed mode */
/* Pass the div id in which PDF should be rendered */
config.divId = divId;
}
/* Initialize the AdobeDC View object */
this.adobeDCView = new window.AdobeDC.View(config);
// alert(fileName + "fileName");
/* Invoke the file preview API on Adobe DC View object */
const previewFilePromise = this.pdfRef = this.adobeDCView.previewFile({
/* Pass information on how to access the file */
content: {
/* Location of file where it is hosted */
location: {
url: fileName, // pdf file url,
/*
If the file URL requires some additional headers, then it can be passed as follows:-
headers: [
{
key: '<HEADER_KEY>',
value: '<HEADER_VALUE>',
}
]
*/
},
},
/* Pass meta data of file */
metaData: {
/* file name */
fileName: 'my filename',
/* file ID */
id: 'my file id'
}
}, viewerConfig);
this.registerSaveApiHandler();
this.registerEventsHandler();
previewFilePromise.then((adobeViewer: any) => {adobeViewer.getAnnotationManager().then((annotationManager: any) => {
// console.log(annotationManager);
annotationManager.addAnnotations(list_of_annotations)
.then(() => console.log("Success"))
.catch((error: any) => console.log(error));
annotationManager.setConfig(customFlags)
.then(() => console.log("Success"))
.catch((error: any) => console.log(error));
annotationManager.registerEventListener((event: any) => {
console.log(event.type, event.data);
switch (event.type) {
case "ANNOTATION_ADDED": this.annotList.push(event.data); break;
case "ANNOTATION_UPDATED": this.updRemAnnot(event.data, 'upd'); break;
case "ANNOTATION_DELETED": this.updRemAnnot(event.data, 'del'); break;
default:
}
},
eventOptions
);
// All annotation APIs can be invoked here
});
});
return previewFilePromise;
}

Update/Delete Annotation Function

updRemAnnot(annotData: any, type: string) {
// console.log(this.annotList, "before");
const index = this.annotList.findIndex((ele: any) => ele.id == annotData.id);
if (index >= 0) {
if (type === 'upd') {
this.annotList[index] = annotData;
} else {
//deleted
this.annotList.splice(index, 1);
}
// console.log(this.annotList, "after");
}
}

Now in the above, I listened to the Annotation events like “ANNOTATION_ADDED”, “ANNOTATION_CLICKED”, “ANNOTATION_UPDATED”, “ANNOTATION_DELETED”

Whenever It clicked I got the event callback and if it added then push that object in an annotation array object, if updated then update that annotation object in the annotation array, and if it's deleted one then I m deleting that object from the array.

Also in the annotation manager, I wrote mention below

annotationManager.addAnnotations(list_of_annotations)

The above function will render all the annotations to the pdf, suppose I have already annotated the pdf, when I want to view again that pdf then I will apply this annotation data and you guys will see the pdf with annotation.

Pdf with Annotation Api Enabled

Now in the above text annotation is there as I enabled annotation api.

For reference, please visit the official documentation of Adobe Embed API

Happy PDF Rendering with Annotation, using Adobe EMbed API.

Happy Coding 😊 with Angular ♥♥♥…

--

--

Vikas Kohli

B.E Software Developer, Enthusiastic, Ego-surfing