In html2pdf library table data is being split in two pages

71 views Asked by At

I'm encountering an issue with page breaks when using the html2pdf library to generate PDFs from HTML. The problem arises when the table in the PDF contains more than a certain number of rows; the data gets cut between pages.

Here is my code, I am getting error if I tried all of things like page break avoid and all other things but nothing is working for me.

am using this code for show table in the pdf with multiple data in table in this if table have 2 data then it works fine when data becomes more then 3 or under 6 then data being cut in between pages.

here is the code for create the pdf, am using this element for create the pdf.

  const element = `
    <!DOCTYPE html>
    <html lang="en">

    <style> 
        .table_column_1{
            width: 5%;
        }
        .table_column_2{
            width: 65%;
        }
        .table_column_3{
            width: 10%;
        }
        .table_column_4{
            width: 10%;
        }
        .table_column_5{
            width: 10%;
        }
        #details tr:nth-child(3) td {
            padding-top: 30px;
        }
        .qua_table {
            page-break-before: always;
        }
    </style>

I'm seeking insights and suggestions on how to ensure proper page breaks in the generated PDF, especially when dealing with tables with a larger number of rows. Are there any specific considerations or adjustments I should make to my code or styles?

    <body>
        <div class="parent-div">
            <div class="child-div">
                <img src="${image_changed}" style="max-width: 100px; height: auto; margin-left:-10px;">
            </div>
            <div class="child-div" style="align-self: center; text-decoration: underline;">
                <p class="heading" style="font-size: 12px; font-weight: bold;">
                    <span style="border-bottom: 1px solid black;">Estimate</span>
                </p>
            </div>
            <div style="text-align:end; align-self: center; flex-direction:row;" class="child-div">
                <div>
                    <span style="font-size: 10px; display: inline-block; text-align: left;">Estimate#</span>
                    <span style="font-size: 10px; display: inline-block; text-align: left;">${response}</span>
                </div>
                <div>
                    <span style="font-size: 10px; display: inline-block; text-align: left;">Date</span>
                    <span style="font-size: 10px; display: inline-block; text-align: left;">${formattedDate}</span>
                </div>
            </div>
        </div>
        
        <table width="100%" style="margin-top:0px;" id="details">
            <tr>
                <td style='font-weight: bold; font-size: 13px; width:10%;'>Customer</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${customerName}</td>

                <td style='font-weight: bold; font-size: 13px; width:10%;'>Ship To</td>
                <td style="font-size: 13px;" colspan=3>${ship_custname}</td>
            </tr>
            <tr>
                <td style='font-weight: bold; font-size: 13px; width:10%; padding-top: 10px;'>Address</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${address}</td>

                <td style='font-weight: bold; font-size: 13px; width:10%; padding-top: 10px;'>Address</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${ship_address}</td>
            </tr>
            <tr>
                <td style='font-weight: bold; font-size: 13px; width:10%;'>City</td>
                <td style="font-size: 13px; width: 10%;" >${customerCity}</td>
                
                <td style='font-weight: bold; font-size: 13px; width:10%;'>Pin code</td>
                <td style="font-size: 13px;" >${pincode}</td>
                
                <td style='font-weight: bold; font-size: 13px; width:10%;'>City</td>
                <td style="font-size: 13px; width: 10%;" >${shipCity}</td>
                
                <td style='font-weight: bold; font-size: 13px; width:10%;'>Pin code</td>
                <td style="font-size: 13px;" >${ship_pincode}</td>
            </tr>
            <tr>
                <td style='font-weight: bold; font-size: 13px; width:10%; padding-top: 10px;'>Mobile</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${mobile}</td>
                
                <td style='font-weight: bold; font-size: 13px; width:10%; padding-top: 10px;'>Mobile</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${ship_mobile}</td>
            </tr>
            <tr>
                <td style='font-weight: bold; font-size: 13px; width:10%; padding-top: 10px;'>GST</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${gst}</td>
                
                <td style='font-weight: bold; font-size: 13px; width: 5%; padding-top: 10px;'>GST</td>
                <td style="font-size: 13px; padding-top: 10px;" colspan=3>${gst}</td>
            </tr>   
        </table>

        <div class="qua_table">
            <table class="table table-striped table-bordered" style="text-align: center;">
                <thead>
                    <tr>
                        <th style="font-size: 13px;">#</th>
                        <th style="font-size: 13px;">Item Details</th>
                        <th style="font-size: 13px;">Quantity</th>
                        <th style="font-size: 13px;">Rate</th>
                        <th style="font-size: 13px;">Amount</th>
                        <th style="font-size: 13px;" colspan="2">Image</th>
                    </tr>
                </thead>
                <tbody>
                    // in this tbody all this rows data in other variable and that variable is in the loop and creating rows values in the table,
                    but for now to make simple to understand i added the code in this tbody

                    <tr class="page-break">
                        <td style="vertical-align: top; font-size: 13px; width: 20px;" class="table_column_1">${indexValues+1}</td>
                        <td style="vertical-align: top; position: relative; padding: 0; margin: 0;" class="table_column_2">
                            <div style="text-align: left; padding: 0; margin: 0;">
                                <span style="font-size: 13px; font-weight: bold;">${selectedName}</span>
                            </div>
                            <div style="text-align: left; margin-top: 5px; padding: 0; margin: 0; margin-top:10px;">
                                <span style="font-size: 13px;">${product_discription}</span>
                            </div>
                            <div style="text-align: left; margin-top: 10px;">
                                ${product_web_link && `<a onclick="window.open(${product_web_link},'_blank');return false;" href="${product_web_link}"  style="font-size: 13px; margin-right: 20px;">For more info on this item click</a>`}
                                ${product_youtube_link && `<a onclick="window.open(${product_youtube_link},'_blank');return false;" href="${product_youtube_link}"  style="font-size: 13px;">Click for Video of this item.</a>`}
                            </div>
                            <div style="text-align: left; background: black; color: white; margin-top: auto; position: absolute; bottom: 0; width: 100%; padding: 0; margin: 0;">
                                <span style="font-size: 13px;">${descriptionText}</span>
                            </div>
                        </td>
                        <td style="vertical-align: top;" class="table_column_3">
                            <span style="text-align: center; font-size: 13px;">${quantityInput}</span>
                            <span style="text-align: center; font-size: 13px;">${unit}</span>
                        </td>
                        <td style="vertical-align: top;" class="table_column_4">
                            <span style="text-align: right; display: block; white-space: nowrap; font-size: 13px;">${new_box_1.checked ? '₹ '+price : '₹ '+netrate}</span>
                            <span style="text-align: right; display: block; white-space: nowrap; font-size: 13px;">${new_box_1.checked &&  dis_1 ? 'Disc %: '+ dis_1 + '%' : ''}</span>
                            <span style="text-align: right; display: block; white-space: nowrap; font-size: 13px;">${new_box_1.checked && dis_2 ? 'Disc 2%: '+ dis_2 + '%' : ''}</span>
                            ${netrate ? `<span style="text-align: right; display: block; white-space: nowrap; font-size: 13px;">${'Net Rate : '+'₹ '+ netrate}</span>`: ''}
                        </td>
                        <td style="vertical-align: top;  text-align: right;" class="table_column_5">
                            <span style="text-align: right; white-space: nowrap; font-size: 13px;">${new_box_1.checked ? '₹ '+(netrate * quantityInput).toFixed(2): '₹ '+amt.toFixed(2) }</span>
                            <br>
                            ${new_box.checked?   
                                `<span style="text-align: right; white-space: nowrap; font-size: 13px;">${'Tax: '+ new_tax+'%'}</span>
                                <br>
                                <span style="text-align: right; white-space: nowrap; font-size: 13px;">${'Taxable: '+ (parseFloat(value_after_tax)).toFixed(2)}</span>`
                                :
                                ''
                            }
                        </td>
                        <td style="vertical-align: middle; padding:0px!important;" class="table_column_6" id="table_column_6" colspan="2">
                            <div style="width: auto; height: 130px; overflow: hidden;">
                                <img src="${item_img.attr('src')}" style="width: auto; height: 100%;">
                            </div>
                        </td>
                    </tr>
                </tbody>
                // here am using the footer for show the calculation and things which is comming from the input fields.

                <tfoot>
                    // Like it is showing total amount and taxable value on the basis of the condition 
                    ${discount > 0 ? 
                        `<tr>
                            <td colspan="3"></td>
                            <td style="text-align: right; font-size: 13px;">Total Amount:</td>
                            <td style="text-align: right; white-space: nowrap; font-size: 13px;">${'₹ '+total}</td>

                            ${new_box.checked ? 
                                `<td style="text-align: right; font-size: 13px;">Taxable:</td>
                                <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+gstTotal}</td>`
                                :
                                ''
                            }
                        </tr>`
                        :
                        ''
                    }

                    // it is showing discount and total taxes on the basis of the condition 
                    ${discount > 0 ?
                        `<tr>
                            <td colspan="3"></td>
                            <td style="text-align: right; font-size: 13px;">Discount: ${discount+'%'}</td>
                            <td style="text-align: right; font-size: 13px;">${'₹ '+discountTotal}</td>

                            ${new_box.checked ? 
                                `<td style="text-align: right; font-size: 13px; white-space: nowrap;">Total Taxes:</td>
                                <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ ' + new_total}</td>`
                                :
                                ''
                            }
                        </tr>` 
                        :
                        ''
                    }

                    // it is showing sub total and Taxable, Total on the basis of the condition 
                    <tr>
                        <td colspan="3"></td>
                        <td style="text-align: right; font-size: 13px;">Sub Total:</td>
                        <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+gstTotal}</td>

                        ${new_box.checked && !discount ? 
                            `<td style="text-align: right; font-size: 13px;">Taxable:</td>
                            <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+gstTotal}</td>`
                            :
                            ''
                        }
                        ${new_box.checked && discount? 
                            `<td style="text-align: right; font-size: 13px;">Total:</td>
                            <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+grand_total}</td>`
                            :
                            ''
                        }
                    </tr>

                    // it is showing freight value and other total taxes on the basis of the condition 
                    ${freight_value ?
                    `<tr>
                        <td colspan="3"></td>
                        <td style="text-align: right; font-size: 13px;">Freight:</td>
                        <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+freight_value+'.00'}</td>
                        ${new_box.checked && !discount? 
                            `<td style="text-align: right; font-size: 13px; white-space: nowrap;">Total Taxes:</td>
                            <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ ' + new_total}</td>`
                            :
                            ''
                        }
                    </tr>`
                    :
                    ''
                    }

                    //  it is showing grand total on the basis of the condition 
                    <tr>
                        <td colspan="3"></td>
                        <td style="text-align: right; font-size: 13px;">Total:</td>
                        <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+grand_total}</td>
                        ${new_box.checked && !discount? 
                        `<td style="text-align: right; font-size: 13px;">Total:</td>
                        <td style="text-align: right; font-size: 13px; white-space: nowrap;">${'₹ '+grand_total}</td>`
                        :
                        ''
                    }
                    </tr>
                    
                    // in this am sending the grand total vlaue in the convertAmountToWords function 
                        and that function is returning the text as words of amount and showing that words here.
                    <tr>
                        <td colspan="7" style="text-align: center; font-weight: bold; font-size: 13px;">${convertAmountToWords(grand_total)}</td>
                    </tr>
                </tfoot>
            </table>
        </div>
    </body>
    </html>
`;

in this table data for now i fixed the data but it is not one column it can be one two or any fields user want to add in the table will show here, i just added the data in this tbody.

element is the variable in which full html is stored and then all the html data is going for create pdf.

 var opt = {
    margin: [15, 15],
    filename: `Estimate.pdf`,
    image: {
        type: 'jpeg',
        quality: 0.5
    },
    html2canvas: {
        scale: 3,
        letterRendering: true
    },
    jsPDF: {
        unit: 'pt',
        format: 'letter',
        orientation: 'landscape'
    },
    pagebreak: { mode: 'avoid-all', }
};

I'm seeking insights and suggestions on how to ensure proper page breaks in the generated PDF, especially when dealing with tables with a larger number of rows. Are there any specific considerations or adjustments I should make to my code or styles?

Any assistance or guidance on resolving this page break issue would be highly appreciated. Thank you!

window.html2pdf()
    .set(opt)
    .from(element)
    .toPdf()
    .output('bloburl')
    .then(function(pdfas) {
        loader.classList.add('hidden');
        window.open(pdfas);
    });
0

There are 0 answers