Search code examples
javascriptpromisees6-promisejspdfhtml2canvas

Wait for all the HTML to PDF conversion before exporting as pdf


I am trying to export graphs from HTML to pdf using html2canvas library. I am first taking all the divs using a for loop and generating corresponding image for them, and once all the conversion is done, I am calling doc.save("file.pdf"); function to save it. However, I have to call doc.save() function inside a timeout after the for loop is done, since html2canvas('div_id').then() which is responsible to converting html to images, is returning a promise and converting the html to image asynchronously. Is there a way where I can use promise and not setTimeout method. I am not able to come up with a solution using promise.

exportGraphonClick() {
   var metrics  = ["1", "2", "3","4","5","6"];
   var pageCount;
   var doc = new jsPDF("p", "mm"); 

    // loop
    metrics.map((key,index) =>{
      let id_val = `graph-id-${index}`; // creating IDs
      const input = document.getElementById(id_val);

      // html to pdf
      html2canvas(input).then((canvas) => {
        const imgData = canvas.toDataURL('image/JPEG');
        var width  = 300;
        doc.addImage(imgData, 'JPEG', 10, 40, width, 100);
        doc.addPage();
        pageCount = doc.internal.getNumberOfPages();
      });
    })  

     // saving pdf  
      setTimeout(()=> {
      doc.save("file.pdf");
    },2000)

}

Solution

  • You can make the function used in map async, and await the call to html2canvas. This will return an array of unresolved Promises. Promise.all() returns a new Promise that will resolve when all provided promises resolve.

    metrics = metrics.map(async (key, index) => {
        let id_val = `graph-id-${index}`; // creating IDs
        const input = document.getElementById(id_val);
    
        // html to pdf
        let canvas = await html2canvas(input);
        const imgData = canvas.toDataURL('image/JPEG');
        let width  = 300;
        doc.addImage(imgData, 'JPEG', 10, 40, width, 100);
        doc.addPage();
        pageCount = doc.internal.getNumberOfPages();
    })  
    
    // saving pdf
    Promise.all(metrics)
    .then(() => doc.save("file.pdf"))
    .catch(err => console.log(err));