2 Things:
When getting access to a DOM Element in react you should always use useRef
It appears that .html method is async and requires a callback
A working example would be something like this:
import { useRef } from 'react';
import { jsPDF } from 'jspdf';
export default function PDF() {
const pdfRef = useRef(null);
const handleDownload = () => {
const content = pdfRef.current;
const doc = new jsPDF();
doc.html(content, {
callback: function (doc) {
doc.save('sample.pdf');
}
});
};
return (
<div>
<header ref={pdfRef}>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
</header>
<footer>
<button onClick={handleDownload}>Download</button>
</footer>
</div>
);
}
Update
If you need to control the size you can add additional properties as per documentation cited above:
Option 1 - use the html2canvas option and control the scale:
const handleDownload = () => {
const content = pdfRef.current;
const doc = new jsPDF();
doc.html(content, {
callback: function (doc) {
doc.save('sample.pdf');
},
html2canvas: { scale: 0.5 } // change the scale to whatever number you need
});
};
Option 2 - use width and windowWidth:
const handleDownload = () => {
const content = pdfRef.current;
const doc = new jsPDF();
doc.html(content, {
callback: function (doc) {
doc.save('sample.pdf');
},
width: 200, // <- here
windowWidth: 200 // <- here
});
};
Answer from SakoBu on Stack Overflow2 Things:
When getting access to a DOM Element in react you should always use useRef
It appears that .html method is async and requires a callback
A working example would be something like this:
import { useRef } from 'react';
import { jsPDF } from 'jspdf';
export default function PDF() {
const pdfRef = useRef(null);
const handleDownload = () => {
const content = pdfRef.current;
const doc = new jsPDF();
doc.html(content, {
callback: function (doc) {
doc.save('sample.pdf');
}
});
};
return (
<div>
<header ref={pdfRef}>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
<div>l kldfjlkasjfld asjflkajf ljfasd'flksdasjf lsdasjfsadf</div>
</header>
<footer>
<button onClick={handleDownload}>Download</button>
</footer>
</div>
);
}
Update
If you need to control the size you can add additional properties as per documentation cited above:
Option 1 - use the html2canvas option and control the scale:
const handleDownload = () => {
const content = pdfRef.current;
const doc = new jsPDF();
doc.html(content, {
callback: function (doc) {
doc.save('sample.pdf');
},
html2canvas: { scale: 0.5 } // change the scale to whatever number you need
});
};
Option 2 - use width and windowWidth:
const handleDownload = () => {
const content = pdfRef.current;
const doc = new jsPDF();
doc.html(content, {
callback: function (doc) {
doc.save('sample.pdf');
},
width: 200, // <- here
windowWidth: 200 // <- here
});
};
// use can you ReactDOMServer.renderToString(element)
import { renderToString } from "react-dom/server";
import { jsPDF } from "jspdf";
export const dow = () => {
let htmlElement = <div>Hello </div>
let elementAsString = renderToString(htmlElement);
var doc = new jsPDF();
doc.html(elementAsString, {
callback: function (doc) {
doc.save("test.pdf");
},
x: 10,
y: 10,
});
};
// use can use this code as function to handle an event
Videos
What Are the Steps to Integrate jsPDF with React?
How Can I Convert HTML to PDF in a React Application?
What Are the Benefits of Using React for HTML-to-PDF Conversion?
» npm install jspdf-react
Rendering react as pdf is generally a pain, but there is a way around it using canvas.
The idea is to convert : HTML -> Canvas -> PNG (or JPEG) -> PDF
To achieve the above, you'll need :
- html2canvas &
- jsPDF
import React, {Component, PropTypes} from 'react';
// download html2canvas and jsPDF and save the files in app/ext, or somewhere else
// the built versions are directly consumable
// import {html2canvas, jsPDF} from 'app/ext';
export default class Export extends Component {
constructor(props) {
super(props);
}
printDocument() {
const input = document.getElementById('divToPrint');
html2canvas(input)
.then((canvas) => {
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF();
pdf.addImage(imgData, 'JPEG', 0, 0);
// pdf.output('dataurlnewwindow');
pdf.save("download.pdf");
})
;
}
render() {
return (<div>
<div className="mb5">
<button onClick={this.printDocument}>Print</button>
</div>
<div id="divToPrint" className="mt4" {...css({
backgroundColor: '#f5f5f5',
width: '210mm',
minHeight: '297mm',
marginLeft: 'auto',
marginRight: 'auto'
})}>
<div>Note: Here the dimensions of div are same as A4</div>
<div>You Can add any component here</div>
</div>
</div>);
}
}
The snippet will not work here because the required files are not imported.
An alternate approach is being used in this answer, where the middle steps are dropped and you can simply convert from HTML to PDF. There is an option to do this in the jsPDF documentation as well, but from personal observation, I feel that better accuracy is achieved when dom is converted into png first.
Update 0: September 14, 2018
The text on the pdfs created by this approach will not be selectable. If that's a requirement, you might find this article helpful.
@react-pdf/renderer is a great resource for this.
It is a bit time consuming converting your markup and CSS to React-PDF's format, but it is easy to understand. Exporting a PDF and from it is fairly straightforward.
To allow a user to download a PDF generated by react-PDF, use their on the fly rendering, which provides a customizable download link. When clicked, the site renders and downloads the PDF for the user.
Here's their REPL which will familiarize you with the markup and styling required. They have a download link for the PDF too, but they don't show the code for that here.
» npm install react-to-pdf
If you are using reactjs just convert your element to html and then pass it to the jspdf like below
import jsPDF from "jspdf";
import ReactDOMServer from "react-dom/server";
export default function App() {
const exportPDF = () => {
let element = (
<div style={{ display: "flex", flexWrap: "wrap" }}>Sample Text</div>
);
const doc = new jsPDF("p", "pt", "letter");
doc.html(ReactDOMServer.renderToString(element), {
callback: function (doc) {
doc.save('sample.pdf');
}
});
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={exportPDF}>export</button>
</div>
);
}
you are passing jsx in my opinion because it is react js.
if you try in a simple project with HTML js and not react js I think you will get result.
for doing this I have a case like you several months ago. finally I did that with node js and not react js. node js and pure html css.