Open labyed opened 6 years ago
i want to know is ther an option if the content of the element is too big and will not be rendered in the rest of the page, then put it in the next page
I think there is not an option for that yet. In my case, I have a table, but some rows were cut. I have solve this by calculating the height of the rows, and if this height was greater than 500px, I insert a page break before of last row. I have done it with jquery.
@lcrojanouninorte can you post the code you used for that, thank you
@labyed it is not the same case, but you can try. I think you have to set a size limit and calculate the size of each element, and put a page every time this pass the limit :
I create a funtion that put page break in a table every 500px, based on the sum of rows of a table. if the sum of rows height is bigger than a limit, in this case 500, then insert a page break. After all page break are set, continue normal with the plugin.
insertBreaks(){
//get table rows in html
var rows = $('#basic-table > tbody > tr')
let current_page_height = 0; //
let max_page_height = 500; //Is the max size of page i want. in px
angular.forEach(rows, function(tr, key){
var row_height = tr.offsetHeight;
current_page_height =current_page_height + row_height
//If the sum of page rows heights are bigger thant my limit, then insert break
if(current_page_height>max_page_height){
current_page_height = 0
$(tr).before( '<div class="html2pdf__page-break"></div>' );
}
})
}
Then first call the function in order to insert the breakes, and continue normal.
download_pdf(){
this.insertBreaks()
var element = document.getElementById('exportthis');
element.style.display = 'block'
let options = {
margin: [22,10, 15, 10], //top, left, buttom, right
filename: 'Gantt.pdf',
image: { type: 'jpeg', quality: 1 },
html2canvas: { dpi: 192, letterRendering: true},
jsPDF: { unit: 'mm', format: 'A4', orientation: 'landscape' },
}
setTimeout(function(){
html2pdf().from(element).set(options).to('pdf').get('pdf').then(pdfCallback, pdfErrorCallback)
},50);
}
@labyed Hi Labyed ! Did you find a solution to work around this ?
So i managed thanks to @lcrojanouninorte basis to create the same kind of function to insert breaks between pages, for text + tables (in my case it's a report). I'm working with Angular 5 btw. There is maybe some needs to adapt it for your situation. I advice people to do some tests.
insertBreaks(element) {
let currentPageHeight = 0;
// this mawPageHeight depends of the dpi of your pdf, your format, etc.
let maxPageHeight = 650;
// select all elements from our created html element which contains our text
let allElem = element.getElementsByTagName('*');
// iterate through the elements to calculate the height and then avoid height repetition from
// elements within other elements by setting their height to 0
for (let i = 2; i < allElem.length; i++) {
// get the height of each element
let lineHeight = allElem[i].offsetHeight;
if (allElem[i].tagName === 'TBODY') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'UL') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'TABLE') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'DIV') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'TD') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'SPAN') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'STRONG') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'U') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'EM') {
lineHeight = 0;
}
else if (allElem[i].tagName === 'P' && allElem[i].parentElement.tagName === 'TD') {
lineHeight = 0;
}
// calculate the total height
currentPageHeight = currentPageHeight + lineHeight;
if (currentPageHeight > maxPageHeight) {
currentPageHeight = 0;
// insert an html page break when max height page is reached
allElem[i].insertAdjacentHTML('beforebegin', '<div class="html2pdf__page-break"></div>');
}
}
return element;
}
pdfyOnClick() {
// create temporary element to insert the html string and sanitize the html to make it readable
let reportInHtmlElem = document.createElement('div');
// we hide it from the user view
reportInHtmlElem.style.visibility = 'hidden';
// below method of inserting html expose to possible XSS security issues but it's the only method i've
// found that is working to insert my html content
// + my html inserted here is created by my rich text editor which is safe
reportInHtmlElem.innerHTML += this.reportInHtml;
document.body.appendChild(reportInHtmlElem);
reportInHtmlElem = this.insertBreaks(reportInHtmlElem);
let opt = {
margin: [50, 20, 20, 20],
enableLinks: true,
filename: 'somefileName',
type: 'jpeg', quality: 1
};
html2pdf().from(reportInHtmlElem).set(opt).toPdf().get('pdf').then(function (pdfObject) {
// function to insert the header img
// get the number of pages in the pdf
let pdf_pages = pdfObject.internal.pages;
let headerImg = 'myImg';
// We are telling our pdfObject that we are now working on this page
pdfObject.setPage(i);
// then we put our img header
pdfObject.addImage(headerImg, 0, 0, 0 , 0);
}}).save();
// make it visible back
reportInHtmlElem.style.visibility = 'visible';
// remove temporary element
document.body.removeChild(reportInHtmlElem);
}
}
Try with following option object:
var opt = {
margin: [15,15],
filename: 'pdfFileName.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 2, letterRendering: true },
jsPDF: { unit: 'pt', format: 'letter', orientation: 'portrait' },
pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
};
@dgolhar Thanks man, you saved my day
Your answer @dgolhar is correct, it has worked for me. Thank's
I wanted to share a solution I found for a common issue with jsPDF where text gets cut off at the end of a page when generating a PDF from HTML content. This can be particularly troublesome when dealing with dynamic or lengthy content.
After experimenting with various settings, I found a combination that works well to prevent text from splitting inappropriately across pages. This code is written in React. Here's the function I used to generate the PDF:
function downloadPdf() { let jsPdf = new jsPDF('p', 'pt', 'letter'); var htmlElement = pdfRef.current; // Reference to the HTML content
const opt = {
callback: function (jsPdf) {
jsPdf.save("Test.pdf");
},
margin: [20, 20, 20, 20], // Set appropriate margins
autoPaging: 'text', // Crucial for handling text flow across pages
html2canvas: {
allowTaint: true,
letterRendering: true,
logging: false,
scale: 0.4, // Adjust the scale to fit content
},
};
jsPdf.html(htmlElement, opt);
}
Key Points:
The autoPaging: 'text' option in jsPDF was particularly useful to ensure the text flows correctly from one page to another.
Adjusting the scale in html2canvas options helped fit the content properly within the PDF pages.
This approach worked well for my use case with dynamic content. I hope this solution helps others who are struggling with similar issues in jsPDF. Feel free to tweak the settings to suit your specific needs!
https://github.com/eKoopmans/html2pdf.js/issues/83#issuecomment-382425018
I used the same logic as lcrojanouninorte - thanks!, however, another approach, which solved my problem.
My problem statement: I have a table of items which I need to convert to PDF. Until
Solution: credits also to my partner @aryarajan
'addBreak'
Disclaimers: "html2pdf__page-break" - did not use this as it wasn't agreeing with me somehow. Also, Im using plain javascript / html.
OnPageLoad - identify row which needs to go to the next page
` function insertBreaks() {
//get table rows in html
var rows = document.querySelectorAll('#itemsTable > tbody > tr');
let current_page_height = 0;
let max_page_height = 500; //adjust max sizeof page in px
rows.forEach(row => {
var row_height = row.offsetHeight;
current_page_height = current_page_height + row_height
//If the sum of page rows heights are bigger thant my limit, then insert break
if (current_page_height > max_page_height) {
current_page_height = 0;
row.classList.add('addBreak');
}
});
}`
CSS:
.addBreak { break-before: auto; margin-top: 70px; }
Html2PDF options:
var options = { margin: [30, 0, 50, 0], filename: filename, image: { type: 'jpeg', quality: 0.9 }, autoPaging: 'text', html2canvas: { scale: 2, logging: true, dpi: 300, letterRendering: true }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'p' }, pagebreak: { avoid: 'tr', mode: ['css'], } };
Hope this helps.
I wanted to share a solution I found for a common issue with jsPDF
@igagandeep So you're using only jsPDF, but not html2pdf.js? Or did you find a way to pass the autoPaging option from html2pdf?
Para funcionar o "pagebreak" atualize a versão do html2pdf pra mais recente! versão abaixo de 0.9.3 não suporta.
Hello, i got a problem with librarie, the text is cut in the middle, is there a way to avoid that, the current behavior :