Search code examples
angularjspdfhtml2canvas

Angular issue with *ngIf HTML elements are not completely rendered before JSPDF generate the pdf


Good day/evening to you guys.

I am currently having a problem where the HTML elements under *ngIf are not completely loaded before the jspdf can generate the pdf.

The .html file related to the problem

<div *ngIf="!templateHide" class="pdfPaper" id="printId">

    <div class='pdfLoop' *ngFor="let t of tempSplitArray">
    
    ...

    </div>

</div

Here are the codes in .ts file.

Function getPdfDataList() which handles the data before generate.

await getPdfDataList(data){

  //*ngIf control
  this.templateHide = false;

  //this ensures the HTML render the element under *ngIf before continue the codes inside. 
  setTimeout(async ()=>{

      this.formId = 'printId';

      //handling data, tempSplitArray is being assigned inside here.
      let complete =  await this.getRawData(data);

      console.log(complete);

      this.generatePDF();

  },0);
}

Function generatePdf() which generates the pdf.

generatePdf(){

  let formId = 'printId';

  //HTML DOM. I tried elementRef also but same result
  let htmLData = document.getElementById(formId);

  //the HTML DOM return correctly including the data
  console.log(htmLData);

  html2canvas(htmLData,{
            onclone: function(clonedDoc){
              clonedDoc.getElementById(formId).style.display = 'block';
            },scale: 2}).then(canvas => {

        //detect browser
        let browserName = this.browserName;

        let paddingTop = 24;
        let imgWidth = 210;
        let pageHeight = 297;
        let imgHeight = canvas.height * 210 / canvas.width;
        let heightLeft = imgHeight;
        let pdf = new jspdf('p', 'mm', 'a4');
        let position = paddingTop;

        const canvas4pdf = canvas.toDataURL("image/png");

        pdf.addImage(canvas4pdf , 'PNG', 0, position, imgWidth, imgHeight);
        heightLeft -= pageHeight;

        while(heightLeft > 1){
          position = heightLeft - imgHeight + paddingTop;
          pdf.addPage();
          pdf.addImage(canvas4pdf , 'PNG', 0, position, imgWidth, imgHeight);
          heightLeft -= pageHeight;
        }

        pdf.setProperties({title:this.titleCaseWord(this.formType)});


        if(browserName=='chrome'){
          //require blob for chrome view
          window.open(URL.createObjectURL(pdf.output("blob")));
        }else{
          pdf.output('dataurlnewwindow');
        }
  }
}

Solution

  • It seems that I have input my code in wrong line. Here are the working codes:

    await getPdfDataList(data){
    
      //*ngIf control
      this.templateHide = false;
      this.formId = 'printId';
    
      //handling data, tempSplitArray is being assigned inside here.
      let complete =  await this.getRawData(data);
      console.log(complete);
     
      setTimeout(async ()=>{
    
          this.generatePDF();
    
      },0);
    
    }
    

    Apparently, the data must be fully rendered alongside the *ngIf switch. After that, calling setTimeout will help refresh the elements under *ngIf including the missing data.