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.