Subscribe to Stuck in an Infiniteloop        RSS Feed
-----

Exporting HTML To PDF

Icon Leave Comment
Exporting part of a webpage to PDF is a solved problem, but it took some digging to find the simplest solution that just worked.

Several hours of googling and trying out snippets here and there, here is the sequence that led to success:

1. html2canvas

This library worked well, but for a single div element it generates a single giant image that is then put into the pdf. Perhaps a series of configuration items could have made this a more viable solution, but I could not find them.

import html2canvas from 'html2canvas';
...
         self.$scope.exportResume = function() {
             console.log("Exporting resume");
             var el = document.getElementById('exportme');
             html2canvas(el, {}).then((canvas) =>{
                 var data = canvas.toDataURL();
                 var docDefinition = {
                     content: [{
                         image: data,
                         height: 700,
                         width: 500
                     }]
                 };
                 var title = "test.pdf";
                 pdfMake.createPdf(docDefinition).download(title);
             });
         };



2. jsPDF

This library is used by the eventual solution, but the original means of usage failed to weird dependency issues. The framework I am in is angularjs with webpack and there are known issues with jsPDF requiring html2canvas in a certain order. Alas, I could not get it work correctly.

import * as jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
...
           self.$scope.exportResume = function() {
             console.log("Exporting resume via jspdf");
             var pdf = new jsPDF();
             pdf.addHTML($("#exportme"),function() {
                 pdf.save('web.pdf');
             });
         };



3. Dumping to a new window

This solution would have been viable except for the fact that once you open this new window all angularjs dom control goes away. I'm not sure why I didn't know that originally, I assumed that at a minimum the already formatted div would at least persist, but alas no. All ng-ifs, etc.... were effectively thrown out and the resultant page looked like garbage.

        self.$scope.exportResume = function() {
            var printContents = document.getElementById('exportme').innerHTML;
            var popupWin = $window.open('', '_blank', 'width=800,height=800');
            popupWin.document.open();
            // popupWin.document.write('<html><body onload="window.print()">' + printContents + '</body></html>');
            popupWin.document.write('<html><body>' + printContents + '</body></html>');
            popupWin.document.close();
        };



4. html2pdf.js - the solution!

https://github.com/e...aster/README.md

As with most things, I stumbled across this library as a secondary answer to a stackoverflow question. Ironically html2pdf.js uses jsPDF and html2canvas under the hood. So presumably I could have come up with a solution with 1 and 2 above, but after a while you tire of dicking around with external libraries.

import html2pdf from 'html2pdf.js'
...
        self.$scope.exportResume = function (){
            let element = document.getElementById('exportme');
            let title = "test.pdf";
            let opt = {
                margin: 0.5,
                filename: title,
                jsPDF: {unit: 'in', format: 'letter', orientation: 'portrait'}
            };
            html2pdf(element, opt);
        };



And that was it! Page breaks were handled correctly and with minimal configuration the resultant pdf looked decent. Hopefully this helps someone in the future if they have a similar problem.

0 Comments On This Entry

 

October 2019

S M T W T F S
  12345
6789101112
131415161718 19
20212223242526
2728293031  

Tags

    Recent Entries

    Recent Comments

    Search My Blog

    0 user(s) viewing

    0 Guests
    0 member(s)
    0 anonymous member(s)