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 jsReportRender

    jsReportRender: 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 be mergeWholeDocument



  • It works.
    Thank you for your assistance.


Log in to reply
 

Looks like your connection to jsreport forum was lost, please wait while we try to reconnect.