Issue with Page Number Rendering in JSReport (Chrome PDF + Handlebars)
-
We are experiencing an issue with JSReport when using Chrome PDF and Handlebars for rendering multi-page PDFs. The current page number is consistently rendered as 1 for all pages, rather than reflecting the correct page index. Despite looping through the $pdf.pages and utilizing the helper function getPageNumber, the page index remains static across all pages.
Issue Details:
Function: jsReportRender
Template Engine: Handlebars
Recipe: Chrome PDF
PDF Utils: Enabled for PDF manipulation
Behavior: In the rendered PDF, the Page {{getPageNumber 0}} of {{getTotalPages ../$pdf.pages}} block in the footer displays "Page 1 of X" on all pages, even though each page should display the correct current page number (1, 2, 3, etc.).
Expectation: The getPageNumber helper should increment the page number for each page rendered.
Current Outcome: The page number is stuck at 1 for all pages.Template
This is jsReportRenderjsReportRender: async ( _id, headerHeight, footerHeight, displayHeaderFooter, header, footer, htmlContent, headerFooterContent ) => { return new Promise((resolve, reject) => { const templateConfig = { id: id, shortid: 'xyz', recipe: 'chrome-pdf', engine: 'handlebars', chrome: { format: 'Letter', marginRight: '20px', marginLeft: '20px', marginTop: headerHeight, marginBottom: footerHeight, displayHeaderFooter: displayHeaderFooter, headerTemplate: header, footerTemplate: footer, mediaType: 'print', }, content: htmlContent }; /** Conditionally add pdfOperations if headerFooterContent is not null*/ if (headerFooterContent) { templateConfig.pdfOperations = [ { type: "merge", template: { content: headerFooterContent, engine: "handlebars", recipe: "chrome-pdf", helpers: ` function getPageNumber (pageIndex) { if (pageIndex == null) { return '' } const pageNumber = pageIndex + 1; return pageNumber; } function getTotalPages (pages) { if (!pages) { return ''; } return pages.length; // Total number of pages } ` }, mergeToFront: true, mergeWholeDocuments: true, renderForEveryPage: false }, ]; } // Render the report return jsreport .render({ template: templateConfig }) .then((out) => { return resolve(out.content); }) .catch((err) => { console.trace(); console.error(err); reject(err); }); }); },
Template
<html> <head> <style> * { box-sizing: border-box; } html, body { margin: 0; padding: 0; width: 100%; height: 100%; } .main { display: flex; flex-direction: column; justify-content: space-between; height: 100%; } .header { width: 100%; padding-top: 20px; border-bottom: 1px solid black; } .footer { width: 100%; padding-bottom: 20px; border-top: 1px solid black; text-align: right; padding-right: 25px; } .header-logo { padding-left: 25px; } .company-logo { height: 50px; object-fit: cover; } .header-content { text-align: right; padding-right: 25px; } </style> </head> <body> {{#each $pdf.pages}} {{#if 0}} <div style="page-break-before: always;"></div> {{/if}} <main class="main"> <header class="header"> // header </header> <footer class="footer"> <span>Page {{getPageNumber 0}} of {{getTotalPages ../$pdf.pages}}</span> </footer> </main> {{/each}} </body> </html>
Config file
const jsreport = require('@jsreport/jsreport-core')({ allowLocalFilesAccess: true, reportTimeout: 300000, reports: { async: true }, logger: { silent: false, error: { transport: 'file', level: 'error', filename: 'logs/error.txt' }, file: { transport: 'file', level: 'info', filename: 'logs/log.txt' }, console: { transport: 'console', level: 'debug', filename: 'logs/console.txt', }, }, templatingEngines: { numberOfWorkers: 4, strategy: 'in-process', templateCache: { max: 100, // LRU cache with max 100 entries, see npm lru-cache for other options enabled: true, // disable cache }, }, });
Injecting the Handlebars engine
jsreport.use(require('@jsreport/jsreport-handlebars')());
Injecting the Chrome PDF recipe
jsreport.use( require('@jsreport/jsreport-chrome-pdf')({ launchOptions: { args: ['--ignore-certificate-errors', '--headless', '--disable-gpu', '--no-sandbox', '--disable-dev-shm-usage'], }, }) );
Injecting PDF Utils for PDF manipulation
jsreport.use(require('@jsreport/jsreport-pdf-utils')()); module.exports = jsreport;
We eagerly await your guidance and a solution to address this inconsistency.
Thank you for your assistance.
-
Can anyone help me on above?
-
Would it be possible to replicate the problem in the playground?
https://playground.jsreport.net/
-
We are not able to replicate the problem in the playground, but it works fine there. Please check the below for reference.
https://playground.jsreport.net/w/anon/PyLGRA04.But the problem is that in my app, we always get 0 for the 3 value when printing the page number.
<html> <head> <style> * { box-sizing: border-box; } html, body { margin: 0; padding: 0; width: 100%; height: 100%; } .main { display: flex; flex-direction: column; justify-content: space-between; height: 100%; } .header { width: 100%; padding-top: 20px; border-bottom: 1px solid black; } .footer { width: 100%; padding-bottom: 20px; border-top: 1px solid black; text-align: right; padding-right: 25px; } .header-logo { padding-left: 25px; } .company-logo { height: 50px; object-fit: cover; } .header-content { text-align: right; padding-right: 25px; } </style> </head> <body> {{#each $pdf.pages}} {{#if 3}} <div style="page-break-before: always;"></div> {{/if}} <main class="main"> <header class="header"> // header </header> <footer class="footer"> <span>Page {{getPageNumber 3}} of {{getTotalPages ../$pdf.pages}}</span> </footer> </main> {{/each}} </body> </html>
-
Try to fix the typo
mergeWholeDocuments
should bemergeWholeDocument
-
It works.
Thank you for your assistance.