PDF Web Viewer
    Preparing search index...

    Angular SDK Integration

    This guide demonstrates how to integrate the PDF Web Viewer SDK with Angular applications, including:

    • Basic SDK usage with PdfSdk for programmatic document manipulation
    • Asset configuration for workers and fonts
    • Memory management best practices
    • SSR compatibility for Angular Universal applications

    Generate component:

    ng generate component components/pdf-viewer
    

    Update src/app/components/pdf-viewer.component.ts:

    import { Component, OnDestroy, OnInit } from '@angular/core';
    import { PdfSdk } from '@avanquest/pdf-web-viewer/sdk';
    import { environment } from '../../environments/environment';

    @Component({
    selector: 'app-pdf-viewer',
    template: `
    <div style="padding: 40px; text-align: center;">
    <h1>PDF Web SDK Demo</h1>
    <div style="background: #f9f9f9; padding: 30px; border-radius: 12px; display: inline-block;">
    <input type="file" (change)="onFileChange($event)" accept=".pdf" [disabled]="!isInitialized" style="margin-bottom: 20px; padding: 10px;" />
    <div>{{ status }}</div>
    </div>
    </div>
    `,
    })
    export class PdfViewerComponent implements OnInit, OnDestroy {
    status = '';
    isInitialized = false;
    private openDocuments: any[] = [];

    async ngOnInit() {
    await this.initPdfSdk();
    }

    async ngOnDestroy() {
    for (const doc of this.openDocuments) {
    await doc.dispose();
    }
    }

    private async initPdfSdk() {
    try {
    await PdfSdk.initialize({
    license: environment.pdfLicenseKey || 'YOUR_LICENSE_KEY',
    /* workerPath and fontsPath are auto-detected from standard locations */
    });
    this.isInitialized = true;
    } catch (error) {
    console.error('Error initializing PDF SDK:', error);
    this.status = 'Failed to initialize PDF SDK';
    }
    }

    private downloadFile(file: Uint8Array, fileName: string) {
    const blob = new Blob([file], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    const a = Object.assign(document.createElement('a'), {
    href: url,
    download: fileName,
    });
    a.click();
    URL.revokeObjectURL(url);
    }

    async onFileChange(event: any) {
    const file = event.target.files?.[0];
    if (!file || !this.isInitialized) return;

    try {
    const document = await PdfSdk.openDocument({ file });
    this.openDocuments.push(document);

    /* Example operation: get page count */
    const pageCount = document.getNumPages();
    console.log(`Document has ${pageCount} pages`);

    /* Save the document */
    const savedFile = await document.exportDocument({ as: 'uint8array' });

    if (savedFile) this.downloadFile(savedFile, file.name);

    await document.dispose();
    this.openDocuments = this.openDocuments.filter((d) => d !== document);

    this.status = '✅ PDF processed successfully';
    } catch (err) {
    console.error('Error during PDF processing:', err);
    this.status = '❌ Failed to process PDF';
    }
    }
    }

    The PDF Web Viewer requires static assets (workers, fonts, translations, stamps) to be available to your Angular application.

    Update angular.json to include these assets (works for both ng serve and ng build):

    {
    "projects": {
    "your-app-name": {
    "architect": {
    "build": {
    "options": {
    "assets": [
    "src/favicon.ico",
    "src/assets",
    {
    "glob": "**/*",
    "input": "node_modules/@avanquest/pdf-web-viewer/public",
    "output": ""
    }
    ]
    }
    }
    }
    }
    }
    }

    Note: This single entry copies all PDF Web Viewer assets (pwv-workers, pwv-fonts, pwv-i18n, pwv-stamps) to your application's output directory. The pwv- prefix avoids conflicts with your application's own assets. This configuration works for both ng serve and ng build.

    Update src/app/app.component.html:

    <div>
    <h1>PDF Web Viewer Angular Integration</h1>
    <app-pdf-viewer></app-pdf-viewer>
    </div>

    Update src/app/app.module.ts:

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';

    import { AppComponent } from './app.component';
    import { PdfViewerComponent } from './components/pdf-viewer.component';

    @NgModule({
    declarations: [AppComponent, PdfViewerComponent],
    imports: [BrowserModule],
    providers: [],
    bootstrap: [AppComponent],
    })
    export class AppModule {}

    Start development server:

    ng serve
    

    Open browser at http://localhost:4200.

    The SDK automatically handles SSR environments (Angular Universal) by detecting the Node.js context.

    By default, during SSR the SDK will:

    1. Detect SSR environment using typeof window === 'undefined'
    2. Skip asset fetching (workers, fonts, translations, stamps) to prevent server errors
    3. Return default paths/empty manifests - actual loading happens client-side after hydration

    This works for most use cases where PDF functionality is only needed in the browser.

    If you need to pre-resolve asset paths during SSR, set the SSR_BASE_URL environment variable:

    // server.ts
    process.env.SSR_BASE_URL = 'http://localhost:4200'; /* Or your production URL */

    When SSR_BASE_URL is set, the SDK will:

    1. Use it as the base URL for fetching manifests during SSR
    2. Attempt to resolve hashed asset filenames server-side
    3. Gracefully fall back to defaults if fetches fail
    • Without SSR_BASE_URL: Assets load client-side only (recommended for most apps)
    • With SSR_BASE_URL: Assets can be pre-resolved server-side (for optimization)
    • The SDK gracefully handles fetch failures during SSR to prevent server crashes
    • Client-side hydration will use relative URLs as normal

    Make sure you call await PdfSdk.initialize() before any other SDK operations.

    Check that:

    • Worker files are correctly copied via angular.json assets configuration
    • Files are accessible at /pwv-workers/manifest.json (check browser DevTools Network tab)
    • If using custom paths, ensure workerPath matches your assets output location

    If you see "Failed to parse URL" errors during SSR:

    • Set process.env.SSR_BASE_URL to your server's URL if you need SSR asset loading
    • Without SSR_BASE_URL, the SDK skips asset fetching during SSR (this is normal)
    • The SDK will return empty manifests on SSR to prevent crashes - assets load client-side