html to pdf using jsPdf is not working with react app
Asked Answered
B

3

5

I am using react as a frontend application, I want to export a portion of react component as pdf file using jsPdf.

const handleDownload = () => {
  const content = document.getElementById('download-content');
  const doc = new jsPDF();
  doc.html(content);
  doc.save("a4.pdf");
}

React return component is:

return (
<body>
  <header id='download-content'>
    <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>
</body>
)

After click on Download button I want a pdf file which consists header tag data with style. But here I got blank pdf with this function handleDownload.

I don't want to use canvas to generate image and then make pdf.. If I use canvas then, when page size minimize the pdf will change.

How can I get exact html generated page as pdf?

Bowyer answered 4/3, 2022 at 9:39 Comment(0)
A
6

2 Things:

  1. When getting access to a DOM Element in react you should always use useRef

  2. 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
    });
};
Angilaangina answered 6/3, 2022 at 9:28 Comment(5)
Thank you. But the full div tag not show. It's cuttoff half content. How can I got properly all things. Also, when I do responsive the content got in pdf not remain same. It also become like response.. but I want it as standard as full page viewBowyer
You can add width and windowWidth as per the documentation based on your needs. See updated answerAngilaangina
@JhonArab Basically you need to look at all the options the lib provides and figure out how to use it for your needs...Angilaangina
thank you so much. You are superb.Bowyer
hey @SakoBu, what do I do if I want to add a page to the document, inside this callback? thanks!Diffraction
D
1
// 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 
Deference answered 20/6, 2022 at 19:18 Comment(0)
D
0

If I understood your question correctly

Here is my approach to your question:

 const handleDownload = ()=>{
//content retrieves the element.
let content  = document.getElementById("download-content")
/*
 content2 retrieves the HTML code using ".outerHTML" as a string , 
 then add a line break between two opening tags, 
 as well as a line break between a closing tag and an opening tag 
 with the use of .replace and regexp
 */
let content2 = content.outerHTML.replace(/<(\w+)>(.*?)/g, '\n<$1>\n$2').replace(/(<\/\w+>)/g, '\n$1\n')
var doc = new jsPDF()
// This allows adding text to a PDF. 
doc.text(content2, 10 , 10)
doc.save("a4.pdf")

}

I hope this response meets your needs.

Deference answered 6/7, 2023 at 19:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.