user24384837
user24384837

Reputation:

Issues with jsPDF

So I recently started learning HTML/JavaScript. I am trying to create a page where the information entered can then be stored in a PDF for saving/printing. I have had a lot of issues trying to get this to work, so I went in search of some basic code just so I could see that jsPDF works before continuing with my project. This is the code that I found:

// Create a function to generate the PDF
function generatePDF() {
  const doc = new jsPDF();
  doc.text('Hello, World!', 10, 10);
  doc.save('my-document.pdf');
}

// Attach the function to the button click event
document.getElementById('cmd').addEventListener('click', generatePDF);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.3/jspdf.umd.min.js"></script>

<div id="abc">
  <!-- Your content here -->
  <p>Hello, World!</p>
</div>
<button id="cmd">Generate PDF</button>

The issue I have is that this is also giving an error when inspected through edges dev tools. This is the error I'm catching:

Uncaught ReferenceError: jsPDF is not defined at HTMLButtonElement.generatePDF

Being so new to this I really have no idea why it is giving me this error.

I have tried multiple different library references for jsPDF all to that same result.

Upvotes: 3

Views: 1175

Answers (2)

merrais
merrais

Reputation: 401

I have the same issue in nodejs, I use this code

const jspdf = require('jspdf');
const file = new jspdf.jsPDF("p", "mm", "a4");

and it worked as intended

Upvotes: 0

rozsazoltan
rozsazoltan

Reputation: 8508

Solution

The latest released version of jspdf is not 2.5.3 but 2.5.1. Accordingly, I have inserted a new CDN. See here: https://www.npmjs.com/package/jspdf

jspdf does not expose a class to you directly, instead, it places a property named jspdf into the window object as a global variable, from which we can instantiate the class. I have done this. Your code should now be functional.

// Create a function to generate the PDF
function generatePDF() {
  const { jsPDF } = window.jspdf;
  const doc = new jsPDF();
  doc.text('Hello, World!', 10, 10);
  doc.save('my-document.pdf');
}

// Attach the function to the button click event
document.getElementById('cmd').addEventListener('click', generatePDF);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js" integrity="sha512-qZvrmS2ekKPF2mSznTQsxqPgnpkI4DNTlrdUmTzrDgektczlKNRRhy5X5AAOnx5S09ydFYWWNSfcEqDTTHgtNA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="abc">
  <p>Hello, World!</p>
</div>
<button id="cmd">Generate PDF</button>

Is the window. object invocation optional?

As @slebetman's comment also points out, since JavaScript searches for the invoked variable at every level, if your jspdf variable is not declared, then the window.jspdf parameter is invoked instead. You can read more about this behavior here: What's the difference between a global variable and a 'window.variable' in JavaScript? - Stack Overflow answer

I would like to highlight an important detail from the linked description, with which I can identify, questioning whether we are simplifying the code or not:

Since I have to double check whether it's a typo or not, I personally find it more readable to set window.foo directly. (Source)

Consequently, you can simplify your code by omitting the window. invocation, but it's important to note that the creator of the jspdf package declared the variable's value there.

// Create a function to generate the PDF
function generatePDF() {
  const doc = new jspdf.jsPDF();
  doc.text('Hello, World!', 10, 10);
  doc.save('my-document.pdf');
}

// Attach the function to the button click event
document.getElementById('cmd').addEventListener('click', generatePDF);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js" integrity="sha512-qZvrmS2ekKPF2mSznTQsxqPgnpkI4DNTlrdUmTzrDgektczlKNRRhy5X5AAOnx5S09ydFYWWNSfcEqDTTHgtNA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="abc">
  <p>Hello, World!</p>
</div>
<button id="cmd">Generate PDF</button>

Upvotes: 3

Related Questions