How to Build an Angular PDF Viewer with Image Annotation and PDF Export

In today’s digital landscape, web applications often need to handle sophisticated tasks like loading, viewing, and manipulating image files. This article will walk you through building an Angular web application that enables users to load and view image files, add annotations directly to those images, and seamlessly save the annotated images as PDF files. Leveraging the Dynamsoft Document Viewer SDK, you’ll see just how efficiently and quickly you can develop this powerful application.

What you’ll build: A fully functional Angular document viewer that loads images and PDFs, provides nine built-in annotation tools (rectangle, ellipse, polygon, polyline, line, ink, text box, typewriter, stamp), and exports annotated documents as PDF files — all powered by the Dynamsoft Document Viewer SDK.

Key Takeaways

  • Dynamsoft Document Viewer SDK provides a drop-in Angular component for viewing PDF, PNG, JPEG, BMP, and TIFF files with built-in annotation support.
  • The EditViewer class and getDefaultUiConfig API handle all viewer initialization, including toolbar setup and annotation tool registration, in under 20 lines of TypeScript.
  • Nine annotation types (rectangle, ellipse, polygon, polyline, line, ink, text box, typewriter, stamp) are available out of the box — no custom canvas drawing required.
  • This approach works for document review workflows, form markup, and any scenario where users need to annotate and re-export documents in the browser.

Common Developer Questions

  • How do I build an Angular PDF viewer with annotation tools?
  • How do I add image annotation and PDF export to an Angular web app?
  • How do I fix the TS2395 build error when using Dynamsoft Document Viewer in Angular?

Angular PDF Annotation Viewer Demo

Prerequisites

Step 1: Install and Configure the Dynamsoft Document Viewer SDK

1. Clone the Existing Repository

Begin by cloning the repository that already integrates other Dynamsoft SDKs:

git clone https://github.com/yushulx/angular-barcode-mrz-document-scanner.git
cd angular-barcode-mrz-document-scanner

2. Install Dynamsoft Document Viewer SDK

Next, install the Dynamsoft Document Viewer SDK using npm:

npm install dynamsoft-document-viewer

3. Configure Assets in angular.json

To ensure the Document Viewer assets are correctly bundled, add the following configuration to the angular.json file:

{
  "glob": "**/*",
  "input": "./node_modules/dynamsoft-document-viewer/dist",
  "output": "assets/dynamsoft-document-viewer"
}

4. Import and Initialize the Document Viewer SDK

In src/app/product-list/product-list.component.ts, import and initialize the Document Viewer SDK with the following code:

import { DDV } from 'dynamsoft-document-viewer';

...
export class ProductListComponent {
  ...

  async activate(): Promise<void> {
    ...
    try {
      let licenseKey: string = this.inputText === '' ? this.placeholderText : this.inputText;
      await LicenseManager.initLicense(licenseKey, true);

      DDV.Core.engineResourcePath = getFullUrl('assets/dynamsoft-document-viewer/engine/');
      await DDV.Core.init();
      DDV.setProcessingHandler("imageFilter", new DDV.ImageFilter());
      ...
    } catch (error) {
      alert(error);
    }

  }
}

Fix the TS2395 Build Error from Dynamsoft Document Viewer

You may encounter the following TypeScript error during the build process:

TS2395: Individual declarations in merged declaration ‘xxx’ must be all exported or all local

Angular error TS2395

This error typically occurs due to type declaration conflicts within the SDK. You can resolve it by modifying your tsconfig.json file. Add the following configuration:

{
  "compilerOptions": {
    "skipLibCheck": true
  }
}

tsconfig skip lib check

This setting instructs TypeScript to skip type checking of declaration files (.d.ts), which can help avoid conflicts like this in third-party libraries.

Step 2: Create the Angular Document Viewer Component

1. Generate the Document Viewer Component

Start by creating a new Angular component for the Document Viewer with the following command:

ng generate component document-viewer

2. Update the products.ts File

Add a new item to the products.ts file to include the Document Viewer in your product list:


export interface Product {
  id: string;
  name: string;
  description: string;
}

export const products = [
  ...
  {
    id: 'document-viewer',
    name: 'Document Viewer',
    description: 'View, edit and save documents',
  },

];

3. Configure Routing for the Document Viewer

In the app-routing.module.ts file, add a new route to direct users to the DocumentViewerComponent:

...
import { DocumentViewerComponent } from './document-viewer/document-viewer.component';

const routes: Routes = [
  ...
  { path: 'document-viewer', component: DocumentViewerComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

4. Run the Application

Now, start your Angular application to see the new Document Viewer component in action:

ng serve

The new component will appear on the home page:

Angular Document Viewer component

Step 3: Add Image Loading, Annotation, and PDF Export

The Dynamsoft Document Viewer SDK provides both CSS and JavaScript files to facilitate UI and functionality. Follow the steps below to integrate image loading, annotation, and PDF export features into your web page.

1. Include CSS in index.html

Start by adding the necessary CSS file to your index.html to style the document viewer:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="assets/dynamsoft-document-viewer/ddv.css">
</head>

<body>
  <app-root></app-root>
</body>

</html>

2. Create a Container in the Component Template

In document-viewer.component.html, add a <div> element that will serve as the container for the document viewer:

<div id="document_container"></div>

3. Apply CSS for Full-Screen Display

To ensure the document viewer displays full screen, add the following CSS to document-viewer.component.css:

#document_container {
    width: 100%;
    height: 100%;
    position: fixed;
    left: 0;
}

4. Initialize the EditViewer in TypeScript

Next, add the following TypeScript code to document-viewer.component.ts to initialize and configure the document viewer:

import { Component, OnInit } from '@angular/core';
import { DDV, EditViewer } from 'dynamsoft-document-viewer';

@Component({
  selector: 'app-document-viewer',
  templateUrl: './document-viewer.component.html',
  styleUrls: ['./document-viewer.component.css']
})
export class DocumentViewerComponent implements OnInit {
  editViewer?: EditViewer;

  constructor() {

  }

  ngOnInit(): void {
    const mytooltips = DDV.Elements.getTooltip();
    mytooltips.DisplayMode = "Display Mode";
    mytooltips.AnnotationSet = "Add Annotation";
    DDV.Elements.setTooltip(mytooltips);

    let config = DDV.getDefaultUiConfig("editViewer", { includeAnnotationSet: true });
    this.editViewer = new DDV.EditViewer({
      container: "document_container",
      uiConfig: config!,
    });

  }

}

Explanation

  • Tooltip Customization: DDV.Elements.getTooltip() and DDV.Elements.setTooltip() allow you to customize the tooltips displayed in the viewer. By default, tooltips are empty, so these methods enable you to define meaningful labels for UI elements.
  • UI Configuration: DDV.getDefaultUiConfig() retrieves the default UI configuration for the viewer. Setting includeAnnotationSet to true enables annotation tools within the viewer.
  • Viewer Initialization: new DDV.EditViewer() creates a new instance of the EditViewer class, specifying the container element’s ID and applying the UI configuration.

5. Run and Test the Application

You now have a fully functional document viewer that supports loading and editing images (including PDF, PNG, JPEG, BMP, and TIFF formats), adding annotations, and saving the annotated images as PDF files.

Angular MRZ Detection from camera stream

Supported Annotation Types

  • Rectangle
  • Ellipse
  • Polygon
  • Polyline
  • Line
  • Ink
  • Text Box
  • Text Typewriter
  • Stamp

Common Issues and Edge Cases

  • TS2395 error on build: If you see Individual declarations in merged declaration 'xxx' must be all exported or all local, add "skipLibCheck": true to compilerOptions in tsconfig.json. This is caused by type declaration conflicts in the SDK’s .d.ts files.
  • Viewer container not rendering: Ensure the <div id="document_container"> element exists in the DOM before new DDV.EditViewer() is called. In Angular, initialize the viewer in ngOnInit or ngAfterViewInit — not in the constructor.
  • Annotations not appearing in exported PDF: Confirm you are using DDV.getDefaultUiConfig("editViewer", { includeAnnotationSet: true }). Without includeAnnotationSet: true, annotation tools are not loaded and will not be embedded in the PDF output.

API Reference

For further customization of the document viewer, refer to the API documentation.

Source Code

https://github.com/yushulx/angular-barcode-mrz-document-scanner