How to add annotations to PDFs using Angular
This article was first published in October 2023 and was updated in October 2024.
In this blog post, we’ll guide you through the process of adding annotations to PDFs in Angular using ngx-extended-pdf-viewer. In the first part, we’ll walk you through the steps to integrate ngx-extended-pdf-viewer into your project and demonstrate how to add annotations to a loaded PDF. In the second part, we’ll show you how to add annotations programmatically using Nutrient’s Angular PDF library.
Annotations allow users to collaborate on, mark up, and highlight important information within a PDF document. This can be incredibly useful for reviewing drafts, adding feedback, or making notes for future reference.
What is ngx-extended-pdf-viewer?
ngx-extended-pdf-viewer is a PDF viewer component for Angular applications. It extends the capabilities of the PDF.js library, allowing you to display, annotate, and interact with PDF files seamlessly.
Requirements
Before getting started, you’ll need:
When you install Node.js,
npm
is installed by default.
Setup
Go to your terminal and install the Angular command-line interface (CLI). This will help you get up and running quickly with Angular:
npm install -g @angular/cli
Now, open your favorite integrated development environment (IDE). This post uses Visual Studio Code.
Open the terminal and create a new Angular project:
ng new pdf-annotation-app
Choose No
for adding Angular routing and CSS
for the stylesheet.
Change your directory into the newly created folder:
cd pdf-annotation-app
Adding ngx-extended-pdf-viewer
Run the command below to install the ngx-extended-pdf-viewer library via npm
or yarn
. This will install the latest version of the library:
npm install ngx-extended-pdf-viewer
yarn add ngx-extended-pdf-viewer
Now you need to configure the angular.json
file. You’ll add this configuration under the projects > yourProjectName > architect > build > options > assets
section:
"assets": [ "src/favicon.ico", "src/assets", { "glob": "**/*", "input": "node_modules/ngx-extended-pdf-viewer/assets/", "output": "/assets/" } ],
Go to the app.module.ts
file and import NgxExtendedPdfViewerModule
from ngx-extended-pdf-viewer
and pass it to the imports
array:
import { NgxExtendedPdfViewerModule } from 'ngx-extended-pdf-viewer'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, NgxExtendedPdfViewerModule], providers: [], bootstrap: [AppComponent], standalone: true, })
Displaying a PDF
Add your PDF document to the src/assets
directory. You can use our demo document as an example.
There’s one step left to see the PDF file in the browser. Go to the app.component.html
file and replace the contents of app.component.html
with:
<ngx-extended-pdf-viewer [src]="'assets/example.pdf'" [useBrowserLocale]="true" [textLayer]="true" [showHandToolButton]="true" [showPresentationModeButton]="true" [showDownloadButton]="false" ></ngx-extended-pdf-viewer>
There are many configuration options you can use. You can see all the options on the ngx-extended-pdf-viewer website.
Adding annotations
ngx-extended-pdf-viewer provides built-in tools for adding annotations like text comments, highlights, and drawings. Users can interact with these tools to annotate a PDF document.
Now, run your project with the following command:
npm start
Navigate to localhost:4200
to see your PDF file.
You can access the project on GitHub.
Nutrient’s Angular PDF annotation library
Nutrient’s Angular PDF annotation library provides a robust set of features:
- 17 annotation types — Nutrient offers a wide range of annotation types, with even more on the horizon.
- Customization — Tailor annotations to your needs by adjusting colors, shapes, and sizes.
- Cross-device syncing — With server deployment, annotations can be synced seamlessly across multiple devices.
- Real-time comment threads — Enable real-time conversations within documents, fostering collaboration (requires server deployment).
- Customizable tooltips — Design tooltips to suit your specific requirements.
- Framework support — Nutrient supports various web frameworks, eliminating the need to write APIs for different programming languages.
To explore the full capabilities of Nutrient and how it can enhance your project, take a look at our demo.
Integrating Nutrient with Angular
Now you’ll learn how to integrate Nutrient into your Angular project.
Creating a new Angular project
First, create a new Angular project for Nutrient integration:
ng new pspdfkit-web-example-angular
This will ask some configuration questions. Choose No
for routing and CSS
for the stylesheet.
Now, change your directory to this project:
cd pspdfkit-web-example-angular
Adding Nutrient
Install pspdfkit
as a dependency with npm
or yarn
:
npm install pspdfkit
yarn add pspdfkit
Now, add the following to your angular.json
file. Angular will copy the Nutrient library assets to the assets
directory before running your app:
"assets": [ "src/favicon.ico", "src/assets", { "glob": "**/*", "input": "./node_modules/pspdfkit/dist/pspdfkit-lib/", "output": "./assets/pspdfkit-lib/" } ]
Displaying the PDF
Add the PDF document you want to display to the src/assets
directory. You can use our demo document as an example.
-
Replace the contents of
app.component.html
with:
<div class="app"> <div class="toolbar"> Nutrient Angular Application </div> <!-- We'll mount the Nutrient UI to this element. --> <div class="pspdfkit-container"></div> </div>
-
Replace the contents of
app.component.ts
with:
import { Component } from '@angular/core'; import PSPDFKit from 'pspdfkit'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['app.component.css'], standalone: true, }) export class AppComponent { title = 'Nutrient Web SDK Angular Example'; ngAfterViewInit(): void { PSPDFKit.load({ // Use the assets directory URL as a base URL. Nutrient will download its library assets from here. baseUrl: location.protocol + '//' + location.host + '/assets/', document: '/assets/example.pdf', container: '.pspdfkit-container', licenseKey: 'YOUR_LICENSE_KEY_GOES_HERE', // Optional license key. }).then((instance) => { // For the sake of this demo, store the Nutrient Web SDK instance // on the global object so that you can open the dev tools and // play with the Nutrient API. (<any>window).instance = instance; }); } }
The license key is optional; however, you may see a watermark on your PDF files without a key. To get a key, contact Sales.
If you try to run your project, you may get an error stating the mounting container has no height. To fix this issue, add the following styles to the src/app/app.component.css
file:
:host { height: 100%; } .app { position: fixed; width: 100%; height: 100%; top: 0; right: 0; bottom: 0; left: 0; } .toolbar { position: relative; display: flex; align-items: center; height: 64px; width: 100%; padding: 0 24px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); font-family: sans-serif; font-size: 20px; font-weight: 500; color: rgba(0, 0, 0, 0.8); } .logo { margin-right: 20px; } .pspdfkit-container { height: calc(100% - 64px); }
You can access the project on GitHub.
-
Start the app and open it in your default browser:
npm start
yarn start
Adding text annotations to a PDF using Nutrient and Angular
Text annotations enable you to add comments, labels, or other textual information directly to a PDF document, enhancing its interactivity and usability.
Nutrient provides the PSPDFKit.Annotations.TextAnnotation
class to create text annotations and customize them with various properties such as font, color, size, alignment, and position.
-
Inside the
app.component.ts
file, add thecreateTextAnnotation
method to add text annotations to the PDF:
async createTextAnnotation() { const annotation = new PSPDFKit.Annotations.TextAnnotation({ pageIndex: 0, // Specify the page number for the annotation. text: { format: 'plain', value: 'Welcome to PSPDFKit', // Text to embed. }, font: 'Helvetica', isBold: true, horizontalAlign: 'left', // Align the annotation to the left of the bounding box. boundingBox: new PSPDFKit.Geometry.Rect({ left: 50, // Position of the annotation. top: 200, width: 100, height: 80, }), fontColor: PSPDFKit.Color.BLUE, // Color of the text. }); // Attach this annotation to your PDF. const createdAnnotation = await this.pspdfkitInstance.create( annotation, ); console.log('Text annotation created:', createdAnnotation); }
-
Now that you’ve added the
createTextAnnotation
method, it should be called at the right moment. To ensure that the Nutrient instance is loaded and ready, invokecreateTextAnnotation
within thengAfterViewInit
lifecycle hook. Here’s the code to achieve this:
ngAfterViewInit(): void { PSPDFKit.load({ baseUrl: location.protocol + "//" + location.host + "/assets/", document: "/assets/example.pdf", container: ".pspdfkit-container", licenseKey: "YOUR_LICENSE_KEY_GOES_HERE", }).then((instance) => { this.pspdfkitInstance = instance; // Store the Nutrient instance in a variable. // Call the function to create a text annotation. this.createTextAnnotation(); }); }
When you run the application, you can see the text annotation added to the PDF.
Adding ink annotations to a PDF using Nutrient and Angular
To insert ink annotations into your Angular app using Nutrient, follow the steps below.
-
Inside the
app.component.ts
file, add the followingcreateInkAnnotation
function. This method is responsible for creating an ink annotation on a PDF page. It takes four parameters —x1
,y1
,x2
, andy2
— which represent the coordinates of the starting and ending points of the ink annotation:
async createInkAnnotation({ x1, y1, x2, y2, }: { x1: number; y1: number; x2: number; y2: number; }) { const { List } = PSPDFKit.Immutable; const { DrawingPoint, Rect } = PSPDFKit.Geometry; const { InkAnnotation } = PSPDFKit.Annotations; const annotation = new InkAnnotation({ pageIndex: 0, boundingBox: new Rect({ width: 400, height: 100 }), strokeColor: new PSPDFKit.Color({ r: 255, g: 0, b: 255 }), lines: List([ List([ new DrawingPoint({ x: x1, y: y1 }), new DrawingPoint({ x: x2, y: y2 }), ]), ]), }); const createdAnnotation = await this.pspdfkitInstance.create(annotation); console.log("Ink annotation created:", createdAnnotation); } async addInkAnnotation() { await this.createInkAnnotation({ x1: 5, y1: 5, x2: 100, y2: 100, }); }
-
Now, you need to call the
createInkAnnotation
method to actually create the ink annotation on your PDF. To ensure that this happens after the Nutrient instance is loaded, call it inside thengAfterViewInit
lifecycle hook:
ngAfterViewInit(): void { PSPDFKit.load({ baseUrl: location.protocol + "//" + location.host + "/assets/", document: "/assets/example.pdf", container: ".pspdfkit-container", licenseKey: "YOUR_LICENSE_KEY_GOES_HERE", }).then((instance) => { this.pspdfkitInstance = instance; // Store the Nutrient instance in a variable. // Call the function to create an ink annotation. this.createInkAnnotation({ x1: 5, // Starting x-coordinate. y1: 5, // Starting y-coordinate. x2: 100, // Ending x-coordinate. y2: 100, // Ending y-coordinate. }); }); }
Conclusion
In this comprehensive post, you learned about two methods for annotating PDFs in your Angular application: one using ngx-extended-pdf-viewer for basic annotations, and the other leveraging Nutrient, a robust PDF SDK, to achieve advanced annotation functionalities, including text and ink annotations. By integrating these tools, you can develop interactive and collaborative PDF annotation features that greatly enhance your Angular applications.
If you’re interested in exploring Nutrient further, you can request a free trial of our SDK or visit our demo page to experience the capabilities of our product firsthand.