node.jspdfmake

Canvas element causes incorrect rendering when used more than once or in a loop - PDFMake


I'm trying to generate multiple PDFs server side using PDFMake. Each PDF has a certain section that's constant across all PDFs to be generated, general. That general section is then separated by a line and then the information specific to that document is loaded in beneath it.

This works great on the first PDF. On the second, however, the layout breaks. How can I fix this?

First PDF: enter image description here

Second PDF: enter image description here

 "use strict";
  const fs = require("fs");
  const PdfPrinter = require("pdfmake");

  const fonts = {
    Helvetica: {
      normal: "Helvetica",
      bold: "Helvetica-Bold",
      italics: "Helvetica-Oblique",
      bolditalics: "Helvetica-BoldOblique",
    },
  };

  const printer = new PdfPrinter(fonts);

  const general = [{ text: "This is general text" }];

  const first = [{ text: "This is the text for the first pdf" }];

  const second = [{ text: "This is the text for the second pdf" }];

  const line = [{canvas: [{ type: 'line', x1: 0, y1: 5, x2: 595-2*40, y2: 5, lineWidth: 2 }],margin: [ 0, 10, 0, 10 ]},];


  let docDefinition = {
    pageSize: "letter",
    defaultStyle: {
      font: "Helvetica"
    }
  };

  docDefinition.content = [general,line,first];
  let pdfDoc = printer.createPdfKitDocument(docDefinition);
  pdfDoc.pipe(fs.createWriteStream('one.pdf'));
  pdfDoc.end();


  docDefinition.content = [general,line,second];
  pdfDoc = printer.createPdfKitDocument(docDefinition);
  pdfDoc.pipe(fs.createWriteStream('two.pdf'));
  pdfDoc.end();

Solution

  • So I asked a question on the GitHub issues page and the response was:

    One docDefinition variable can be used only once to generate PDF.

    While that may be true I did find an adequate workaround by using a table with just the headerLine. This isn't my idea but I can't remember where I got it from.

    function line() {
      //Usually one would use a canvas to draw the line
      //{canvas: [{ type: 'line', x1: 0, y1: 5, x2: 595-2*40, y2: 5, lineWidth: 2 }],margin: [ 0, 10, 0, 0 ]},
      //For some reason, that's not working and the layout just breaks
        return {
          table : {
            headerRows : 1,
            widths: ['100%'],
            body : [
                    [''],
                    ['']
                    ]
            },
            layout : 'headerLineOnly'
        }
    } 
    

    Then you use line() anywhere in your docDefinition that you need a line.

    "use strict";
      const fs = require("fs");
      const PdfPrinter = require("pdfmake");
    
      const fonts = {
        Helvetica: {
          normal: "Helvetica",
          bold: "Helvetica-Bold",
          italics: "Helvetica-Oblique",
          bolditalics: "Helvetica-BoldOblique",
        },
      };
    
      const printer = new PdfPrinter(fonts);
    
      const general = [{ text: "This is general text" }];
    
      const first = [{ text: "This is the text for the first pdf" }];
    
      const second = [{ text: "This is the text for the second pdf" }];
    
    
    
      let docDefinition = {
        pageSize: "letter",
        defaultStyle: {
          font: "Helvetica"
        }
      };
    
      docDefinition.content = [general,line(),first];
      let pdfDoc = printer.createPdfKitDocument(docDefinition);
      pdfDoc.pipe(fs.createWriteStream('one.pdf'));
      pdfDoc.end();