Search code examples
jspdfjspdf-autotable

How to add a logo to the top of each page using JsPDF-autoTable?


JsPdf-autoTable is a fantastic piece of software and very simple to get the basics working.

Now I want to add a logo and some text at the top of each page and a page X of Y footer on each page, but I can't figure out how. I want to get the image for the logo from a URL (local file on my website).

Is there an easy example somewhere? I think that I do it with JsPdf, rather than JsPdf-autoTable.


Solution

  • The method accepts one parameter:

    doc.autoTable(options);
    

    options, is an object, you can check its properties in the documentation here.

    This options object accepts hooks. You are looking for the didDrawPage hook, which will enable the insertion of a header and a footer.

    didDrawPage: (HookData) => {} - Called after the plugin has finished drawing everything on a page. Can be used to add headers and footers with page numbers or any other content that you want on each page there is an autotable.

    Note: The didDrawPage hook is named addPageContent in versions lower than v3.

    There is already an example on how to do this in the demo. The code is as follows:

    var doc = new jsPDF();
    var totalPagesExp = "{total_pages_count_string}";
    
    doc.autoTable({
        head: headRows(),
        body: bodyRows(40),
        didDrawPage: function (data) {
            // Header
            doc.setFontSize(20);
            doc.setTextColor(40);
            doc.setFontStyle('normal');
            if (base64Img) {
                doc.addImage(base64Img, 'JPEG', data.settings.margin.left, 15, 10, 10);
            }
            doc.text("Report", data.settings.margin.left + 15, 22);
    
            // Footer
            var str = "Page " + doc.internal.getNumberOfPages()
            // Total page number plugin only available in jspdf v1.0+
            if (typeof doc.putTotalPages === 'function') {
                str = str + " of " + totalPagesExp;
            }
            doc.setFontSize(10);
    
            // jsPDF 1.4+ uses getWidth, <1.4 uses .width
            var pageSize = doc.internal.pageSize;
            var pageHeight = pageSize.height ? pageSize.height : pageSize.getHeight();
            doc.text(str, data.settings.margin.left, pageHeight - 10);
        },
        margin: {top: 30}
    });
    
    // Total page number plugin only available in jspdf v1.0+
    if (typeof doc.putTotalPages === 'function') {
        doc.putTotalPages(totalPagesExp);
    }
    
    return doc;
    

    The base64Img variable has to have your image, I've only tested with base64 images, supposedly you can add a hyperlink and it will work if you have the image locally.


    Code Snippet:

    (function() {
    
      function imgToBase64(url, callback) {
        if (!window.FileReader) {
          callback(null);
          return;
        }
        var xhr = new XMLHttpRequest();
        xhr.responseType = 'blob';
        xhr.onload = function() {
          var reader = new FileReader();
          reader.onloadend = function() {
            callback(reader.result.replace('text/xml', 'image/jpeg'));
          };
          reader.readAsDataURL(xhr.response);
        };
        xhr.open('GET', url);
        xhr.send();
      }
    
      var base64Img;
    
      // Convert the image to base64
      // imgToBase64("https://placehold.it/50x50", function(base64) {
      //   base64Img = base64;
      // });
    
      // Static base64 for example purposes
      base64Img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyBAMAAADsEZWCAAAAG1BMVEXMzMyWlpaqqqq3t7exsbGcnJy+vr6jo6PFxcUFpPI/AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAQUlEQVQ4jWNgGAWjgP6ASdncAEaiAhaGiACmFhCJLsMaIiDAEQEi0WXYEiMCOCJAJIY9KuYGTC0gknpuHwXDGwAA5fsIZw0iYWYAAAAASUVORK5CYII='
    
      var headRows = function() {
        return [{
          id: "ID",
          name: "Name",
        }];
      };
    
      var bodyRows = function(rowCount) {
        rowCount = rowCount || 10;
        let body = [];
    
        for (var i = 1; i <= rowCount; i++) {
          body.push({
            id: i,
            name: "Name " + i
          });
        }
    
        return body;
      }
    
      function generate() {
        var doc = new jsPDF();
        var totalPagesExp = "{total_pages_count_string}";
    
        doc.autoTable({
          head: headRows(),
          body: bodyRows(40),
          didDrawPage: function(data) {
            // Header
            doc.setFontSize(20);
            doc.setTextColor(40);
            doc.setFontStyle('normal');
            if (base64Img) {
              doc.addImage(base64Img, 'JPEG', data.settings.margin.left, 15, 10, 10);
            }
            doc.text("Example", data.settings.margin.left + 15, 22);
    
            // Footer
            var str = "Page " + doc.internal.getNumberOfPages()
            // Total page number plugin only available in jspdf v1.0+
            if (typeof doc.putTotalPages === 'function') {
              str = str + " of " + totalPagesExp;
            }
            doc.setFontSize(10);
    
            // jsPDF 1.4+ uses getWidth, <1.4 uses .width
            var pageSize = doc.internal.pageSize;
            var pageHeight = pageSize.height ? pageSize.height : pageSize.getHeight();
            doc.text(str, data.settings.margin.left, pageHeight - 10);
          },
          margin: {
            top: 30
          }
        });
    
        // Total page number plugin only available in jspdf v1.0+
        if (typeof doc.putTotalPages === 'function') {
          doc.putTotalPages(totalPagesExp);
        }
    
        doc.save("headerandfooterexample.pdf");
      }
    
      document.getElementById('download-btn').addEventListener('click', generate);
    
    })()
    <script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>
    <script src="https://unpkg.com/jspdf-autotable"></script>
    <button id="download-btn">Download PDF</button>