<link rel="stylesheet" href="styles-3GBANQL6.css">
← Back to blog

Angular

Angular-Directive to Convert HTML to PDF

Angular-Directive to Convert HTML to PDF

When developing applications, particularly in Angular, there might be cases where you need to allow users to download sections of your website or application as PDFs. Whether it’s an invoice, a report, or any dynamic content, having a seamless method to convert HTML into PDF files becomes invaluable. In this blog, I’ll walk through the creation of a custom directive that can convert HTML elements to PDF using jsPDF and html2canvas.

Why Use a Custom Directive?

Directives in Angular allow you to extend the behavior of elements in the DOM. In this scenario, our directive listens to a click event and generates a PDF version of the HTML element it’s applied to. This keeps the PDF generation logic separated from the component's business logic, making your code cleaner and more modular.

Prerequisites

To follow this tutorial, you should have a basic understanding of Angular and know how to work with directives. We will be using the following external libraries:

  • jsPDF: A library for generating PDF documents in JavaScript.
  • html2canvas: A library that allows you to take "screenshots" of HTML elements and output them as images.

You can install these dependencies using npm:

npm install jspdf html2canvas --save

The HtmlToPdfDirective Implementation

Let’s go over the implementation of the HtmlToPdfDirective.


import { ChangeDetectorRef, Directive, HostListener, inject, Input } from '@angular/core';
import { jsPDF } from "jspdf";
import html2canvas from 'html2canvas';

@Directive({
    selector: '[tfHtmlToPdf]',
    standalone: true,
})
export class HtmlToPdfDirective {
    @Input() fileName!:string;
    @Input() set tfHtmlToPdf(templateRef: HTMLDivElement) {
        this._templateRef = templateRef;
    }
    private _templateRef!: HTMLDivElement;

    constructor(private changeDetectorRef: ChangeDetectorRef) {
    }

    @HostListener('click', [ '$event' ])
    onClick(event: Event) {
        event.preventDefault();
        event.stopPropagation();

        // Trigger change detection before generating the PDF
        // To make sure all changes are reflected during
        // PDF generation (e.g. language changes)
        this.changeDetectorRef.detectChanges();

        this.generatePdf();
    }

    private generatePdf() {
        html2canvas(this._templateRef).then(canvas => {
            const imgData = canvas.toDataURL("image/jpeg", 1.0);
            const doc = new jsPDF('p', 'px', [ canvas.width, canvas.height ]);
            doc.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height);
            doc.save(this.fileName);
        });
    }
}
    

Step-by-Step Breakdown

  1. Directive Decorator (@Directive): The @Directive decorator specifies that this class is an Angular directive. The selector property defines the custom directive as tfHtmlToPdf, which will be used in the component template.
  2. @Input Decorators:
    • @Input() fileName: This input specifies the name of the PDF file that will be generated when the directive is triggered.
    • @Input() set tfHtmlToPdf(templateRef: HTMLDivElement): This input allows you to pass the HTML element (as a reference) to be converted into a PDF.
  3. Change Detection: We inject ChangeDetectorRef into the constructor. This service allows us to manually trigger Angular’s change detection to ensure any content changes are reflected before the PDF is generated.
  4. @HostListener: The @HostListener decorator listens to the 'click' event. When the HTML element this directive is applied to is clicked, it triggers the onClick() method. This ensures that users can generate the PDF by clicking on the respective UI element.
  5. PDF Generation Logic: The generatePdf() method handles the main logic:
    • First, html2canvas converts the target HTML element to a canvas, which can then be manipulated like an image.
    • The canvas is converted to a JPEG image using toDataURL().
    • jsPDF then creates a new PDF document and adds the image to it.
    • Finally, the generated PDF is downloaded with the specified fileName.

How to Use the Directive

Using this directive is simple. You can apply it to any HTML element (like a div) and specify the target element you want to convert into a PDF.

Here’s an example:


<div id="content" #contentRef>
    <h1>This is your content</h1>
    <p>This content will be exported as PDF when you click the button.</p>
</div>

<button [tfHtmlToPdf]="contentRef" fileName="my-content.pdf">
    Download as PDF
</button>
    

In this example:

  • The contentRef reference points to the div element containing the content.
  • The tfHtmlToPdf directive is applied to the button, linking it to the contentRef.
  • Clicking the button triggers the PDF download with the file name my-content.pdf.

Key Considerations

  • Rendering Quality: While html2canvas does a good job of capturing the content, the quality of the PDF depends on the canvas's resolution and the complexity of the HTML being captured.
  • Cross-Browser Compatibility: Ensure that html2canvas and jsPDF are working well in your target browsers, as there may be slight variations in rendering.
  • Large Content: For larger HTML content, you may need to tweak jsPDF settings to properly handle content that spans multiple pages.

Conclusion

By using this simple directive, we can easily export any HTML content as a PDF in an Angular application. Directives like this one make our code modular, reusable, and clean. Whether it’s for invoicing, reporting, or just capturing dynamic content, this approach is powerful and easy to integrate into your project.

Happy coding!

LET'S BUILD WHAT'S NEXT

Ready to turn your idea into a real solution?

Let's discuss how we can help you create value with technology.

Let's Talk