Asked  7 Months ago    Answers:  5   Viewed   488 times

I have the following html code:

<!DOCTYPE html>
<html>
    <body>
        <p>don't print this to pdf</p>
        <div id="pdf">
            <p><font size="3" color="red">print this to pdf</font></p>
        </div>
    </body>
</html>

All I want to do is to print to pdf whatever is found in the div with an id of "pdf". This must be done using JavaScript. The "pdf" document should then be automatically downloaded with a filename of "foobar.pdf"

I've been using jspdf to do this, but the only function it has is "text" which accepts only string values. I want to submit HTML to jspdf, not text.

 Answers

100

jsPDF is able to use plugins. In order to enable it to print HTML, you have to include certain plugins and therefore have to do the following:

  1. Go to https://github.com/MrRio/jsPDF and download the latest Version.
  2. Include the following Scripts in your project:
    • jspdf.js
    • jspdf.plugin.from_html.js
    • jspdf.plugin.split_text_to_size.js
    • jspdf.plugin.standard_fonts_metrics.js

If you want to ignore certain elements, you have to mark them with an ID, which you can then ignore in a special element handler of jsPDF. Therefore your HTML should look like this:

<!DOCTYPE html>
<html>
  <body>
    <p id="ignorePDF">don't print this to pdf</p>
    <div>
      <p><font size="3" color="red">print this to pdf</font></p>
    </div>
  </body>
</html>

Then you use the following JavaScript code to open the created PDF in a PopUp:

var doc = new jsPDF();          
var elementHandler = {
  '#ignorePDF': function (element, renderer) {
    return true;
  }
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
    source,
    15,
    15,
    {
      'width': 180,'elementHandlers': elementHandler
    });

doc.output("dataurlnewwindow");

For me this created a nice and tidy PDF that only included the line 'print this to pdf'.

Please note that the special element handlers only deal with IDs in the current version, which is also stated in a GitHub Issue. It states:

Because the matching is done against every element in the node tree, my desire was to make it as fast as possible. In that case, it meant "Only element IDs are matched" The element IDs are still done in jQuery style "#id", but it does not mean that all jQuery selectors are supported.

Therefore replacing '#ignorePDF' with class selectors like '.ignorePDF' did not work for me. Instead you will have to add the same handler for each and every element, which you want to ignore like:

var elementHandler = {
  '#ignoreElement': function (element, renderer) {
    return true;
  },
  '#anotherIdToBeIgnored': function (element, renderer) {
    return true;
  }
};

From the examples it is also stated that it is possible to select tags like 'a' or 'li'. That might be a little bit to unrestrictive for the most usecases though:

We support special element handlers. Register them with jQuery-style ID selector for either ID or node name. ("#iAmID", "div", "span" etc.) There is no support for any other type of selectors (class, of compound) at this time.

One very important thing to add is that you lose all your style information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3 etc., which was enough for my purposes. Additionally it will only print text within text nodes, which means that it will not print the values of textareas and the like. Example:

<body>
  <ul>
    <!-- This is printed as the element contains a textnode -->        
    <li>Print me!</li>
  </ul>
  <div>
    <!-- This is not printed because jsPDF doesn't deal with the value attribute -->
    <input type="textarea" value="Please print me, too!">
  </div>
</body>
Tuesday, June 1, 2021
 
binoculars
answered 7 Months ago
10

mpdf is another option that you could try.

Wednesday, March 31, 2021
 
Shobit
answered 9 Months ago
93

Okay, I figured this out.

  1. You will need html2canvas and pdfmake. You do NOT need to do any injection in your app.js to either, just include in your script tags

  2. On the div that you want to create the PDF of, add an ID name like below:

     <div id="exportthis">
    
  3. In your Angular controller use the id of the div in your call to html2canvas:

  4. change the canvas to an image using toDataURL()

  5. Then in your docDefinition for pdfmake assign the image to the content.

  6. The completed code in your controller will look like this:

           html2canvas(document.getElementById('exportthis'), {
                onrendered: function (canvas) {
                    var data = canvas.toDataURL();
                    var docDefinition = {
                        content: [{
                            image: data,
                            width: 500,
                        }]
                    };
                    pdfMake.createPdf(docDefinition).download("Score_Details.pdf");
                }
            });
    

I hope this helps someone else. Happy coding!

Saturday, June 5, 2021
 
cyber_truite
answered 6 Months ago
70

Just delete the 2 first line of imports and add the following lines:

var jsPDF = require('jspdf');
require('jspdf-autotable');

You can see an example here

Tuesday, October 12, 2021
 
Warrior
answered 2 Months ago
81

Since you are using jQuery try:

$( document ).ready(function() {
  //console.log( "ready!" );
  PDF1();
});

Also Note: You could use (not required):

var source = $("body")[0];

Code page used to test

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>fromHTML EX</title>
  <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  <meta name="generator" content="Geany 1.22" />

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script src="https://parall.ax/parallax/js/jspdf.js"></script>

  <script type="text/javascript">
  function PDF1(){
    var doc = new jsPDF();
    var elementHandler = {
      '#ignorePDF': function (element, renderer) {
        return true;
      }
    };
    var source = window.document.getElementsByTagName("body")[0];
    doc.fromHTML(
      source,
      15,
      15,
      {
        'width': 180,'elementHandlers': elementHandler
      });

      doc.output("datauri");
    }

    $( document ).ready(function() {
      //console.log( "ready!" );
      PDF1();
    });
</script>

  </head>

  <body>
    ASDSADASDASDSA
    <div>
      <p id="ignorePDF">don't print this to pdf</p>

      <p><font size="3" color="red">print this to pdf</font></p>
    </div>




  </body>
  </html>
Saturday, October 16, 2021
 
Bacon
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share