I have code where I am showing multiple pages using next or previous buttons to see the other pages. The pages are shown and hidden using CSS. However, we want to download all the pages to a PDF book using jsPDF and html2canvas.
If you send the book element to jsPDF it will only show one page in the PDF. That's because on screen we are only showing 1 page at a time. If I show all the pages when you try to download the PDF (update the CSS) then it will save properly but will be a really weird UI experience.
I could create a separate JSX object that shows all the pages at once but never displays on the screen. Then I could access the pages programmatically, looping through the book element's children (the pages), creating images of each page and adding to the PDF book.
I've tried the above approach many times but each time I get an error about not being able to access the children. This is because the block never renders. How do I get a block like this to render without sending it to the screen?
I've been going crazy trying to figure out a solution to this!!
Here's some code to show what I'm trying:
const countChildren = (pdfRef) => {
const numChildren = React.Children.count(pdfRef.current.props.children);
const childContent = pdfRef.current.props.children.map((child) => child.props.children);
return { numChildren, childContent };
};
function Book() {
const pdfRef = useRef(null);
const downloadPDF = async () => {
const pdfDoc = new jsPDF({
orientation: "landscape",
format: printSize,
unit: "in",
});
//content.children[0].children.length
//pdfRef.current.children.length
const { totalPages, childContent } = countChildren(pdfRef); // get total number of pages
console.log('totalPages',totalPages);
for (let i = 1; i <= totalPages; i++) {
const pageContent = pdfRef.current.children[i - 1]; // get page content element
const canvas = await html2canvas(pageContent); // convert page content to canvas
const imgData = canvas.toDataURL("image/png"); // convert canvas to image data
pdfDoc.addImage(imgData, "PNG", 0, 0, 11.7, 0, null, "SLOW");
if (i < totalPages) {
pdfDoc.addPage();
}
}
pdfDoc.save("book.pdf");
};
const bookPDF = () => {
return (
<BookContainer className="pdf" ref={pdfRef}>
{BookData.pages.map((item, index) => {
return (
<Page className="pdf" key={index} show={currentPage === index + 2 ? true : false}>
{item.animal} {item.environment} {item.copy}
</Page>
);
})}
</BookContainer>
);
};
return (
<>
<BookContainer>
{BookData.pages.map((item, index) => {
return (
<Page key={index} show={currentPage === index + 2 ? true : false}>
{item.animal} {item.environment} {item.copy}
</Page>
);
})}
</BookContainer>
<PageNavigation />
<Button onClick={downloadPDF}>
Download PDF
</Button>
</>
);
}