Reader Stacks

Multiple Ways to Convert HTML to PDF in Angular

Client-side PDF generation trades server load for real rendering-fidelity limits — for anything needing pixel-perfect output, generating the PDF server-side remains the more reliable choice.

Generating a PDF directly in the browser from Angular avoids a server round-trip, but it comes with genuine rendering fidelity trade-offs compared to server-side generation (covered separately for Laravel's DomPDF elsewhere on this site) — worth understanding before choosing this approach for something needing precise, print-quality output.

Using jsPDF for programmatic PDF generation

npm install jspdf
import jsPDF from 'jspdf';

generateInvoice() {
    const doc = new jsPDF();
    doc.text('Invoice #1001', 10, 10);
    doc.text('Total: $150.00', 10, 20);
    doc.save('invoice.pdf');
}

jsPDF builds a PDF programmatically — text, lines, shapes — giving precise control over the output, but it means the layout is defined in code rather than derived from existing HTML/CSS, which can mean more manual work for a genuinely complex layout.

Using html2canvas + jsPDF to capture an existing DOM element

npm install html2canvas jspdf
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

async exportToPdf() {
    const element = document.getElementById('invoice-content')!;
    const canvas = await html2canvas(element);
    const imgData = canvas.toDataURL('image/png');

    const doc = new jsPDF();
    const imgWidth = 190;
    const imgHeight = (canvas.height * imgWidth) / canvas.width;

    doc.addImage(imgData, 'PNG', 10, 10, imgWidth, imgHeight);
    doc.save('invoice.pdf');
}

This approach captures an existing HTML element as a rendered image, then embeds that image into a PDF — it genuinely preserves your actual CSS styling, but the result is a rasterized image, not selectable text, which matters if the PDF needs to support text search or copy-paste.

Using window.print() with print-specific CSS, as a simpler alternative

@media print {
    .no-print { display: none; }
    body { font-size: 12pt; }
}
printInvoice() {
    window.print();
}

This leans on the browser's own native "print to PDF" capability rather than generating a PDF file directly — genuinely simpler to implement, and it produces real, selectable text (not a rasterized image), but it depends on the browser's own print dialog rather than giving a direct downloadable file with a single button click.

Calling a server-side PDF generation endpoint instead

this.http.get('/api/invoices/1001/pdf', { responseType: 'blob' }).subscribe(blob => {
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'invoice.pdf';
    a.click();
});

Delegating to a server-side PDF generator (like the Laravel DomPDF approach covered elsewhere on this site) gives the most reliable, print-quality, text-selectable output — worth the extra server round-trip for anything where PDF quality and fidelity genuinely matter more than avoiding a network request.

Choosing between these approaches

jsPDF alone suits simple, code-defined documents; html2canvas+jsPDF suits quickly capturing existing styled content at the cost of text selectability; window.print() suits a low-effort, browser-native solution; and server-side generation remains the most reliable choice for anything needing genuine document quality, like an invoice or contract meant to be archived or emailed.