1

my below code is working fine but i want all pages in one PDF. i have 2 json object. when i click on button its open in 2 tab with different result i want its open in one pdf tab add multiple records in multiple pages in one pdf. can you help me on this.

for (let i = 0;i  <= this.reportVGWM.length; i++){
          html2canvas(document.querySelector('#myTable' + i)).then(canvas => {
            var imgWidth = 180;
            var pageHeight = 280;
            var imgHeight = canvas.height * imgWidth / canvas.width;
            var heightLeft = imgHeight;
            var imgData = canvas.toDataURL("image/jpeg");
            var heightLeft = imgHeight;
            var pdf = new jsPDF('p', 'mm', 'a4');
            var position = 20;
            var font: { 'padding-bottom: 40%; padding-top:30%' };
            pdf.addImage(imgData, 'PNG', 10, position, imgWidth, imgHeight);
            pdf.addPage();                 
            pdf.output('dataurlnewwindow');

          });
        }
        }, 1);
      });
vik_78
  • 1,107
  • 2
  • 13
  • 20
Nitesh
  • 11
  • 1
  • 2
  • Find a good solution here: https://stackoverflow.com/questions/27045704/how-do-i-get-a-multi-page-pdf-from-a-website-using-jspdf-and-html2canvas – Mark Jan 15 '21 at 09:39

1 Answers1

2

you can use pdfMake, another amazing js library. I got these infos in this question: Generating PDF files with JavaScript

printDocument() {
  const divs = document.getElementsByClassName('example');
  const newList = [].slice.call(inputs);
  var contentArray = []
  var docDefinition = {
            pageSize: {width: 800, height: 1173},
            content: [
                {
                    text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.'
                }
            ]

        }

  Promise.map(newList, async (element, index) => {
            let canvas = await html2canvas(element);
            const imgData = await canvas.toDataURL('image/png');
            // console.log("imgData URL => ", imgData)
            // margin horizontal -40 = removing white spaces
            return contentArray[`${index}`] = [{ image: imgData, width: canvas.width, height: canvas.height, margin: [-40, 0] }, {
                text: ` ${index} - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi.`
}];

        }).then(
            () => ( docDefinition.content.push(contentArray))
        ).then(
            () => {
                console.log("... starting download ...")
                pdfMake.createPdf(docDefinition).download('examplePdf.pdf')
            } 
        )
}

// In your react's component constructor ... 

constructor(props) {
        super(props);
        this.printDocument = this.printDocument.bind(this)
}

// the imports below ...
import Promise from 'bluebird';
import html2canvas from 'html2canvas';
import pdfMake from 'pdfmake/build/pdfmake.js';
import pdfFonts from "pdfmake/build/vfs_fonts.js";
pdfMake.vfs = pdfFonts.pdfMake.vfs;

// i'm using these middlewares
import promise from 'redux-promise'
import multi from 'redux-multi'
import thunk from 'redux-thunk'





<div>
  The approach here is: a div it's not a page. Because if the image generated by the canvas element it's bigger than the page vertical size, we'll need to control the pagination by ourselves. So, we broke our content in small elements to the pdf generator handle the pagination to us. This way we garantee that the pagination will occurs without cuts. 
  <div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >

  // any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.

  </div>
  <div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >

  // any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.

  </div>
  <div className="example" style={{ backgroundColor: '#ffffff', maxWidth: '800px', maxHeight: '1173px', borderStyle: 'groove', borderColor: 'red', margin: '0px' }} >

  // any content or component here, we need maxHeight to be sure that the div's height size it's not bigger than the your PDF doc's height dimension, else your div may never be rendered inside it.

  </div>

</div>

<div>
 <button onClick={this.printDocument}> print using PDFMake  </button>
</div>

Using the Promise.map by bluebird with the async/await resources, we can ensure that we'll wait till the end of generation of all images from canvas. This process can take a while depending of your image's size.

Chandan Kumar
  • 799
  • 7
  • 23