Reputation: 501
I need to print a list of elements on the click of a button. I have the data in my back-end, and am generating a table of elements with 5 elements in each row through the following:
const labelDataHTML = (values) => (
<table id="dataTable" style={{ width: "100%" }}>
<caption>Labels</caption>
{_.chunk(values, 5).map((item, index) => (
<tr key={`row-${index}`} className={`row`}>
{index % 5 !== 0
? item.map((obj) => <td>{obj}</td>)
: item.map((obj) => <td>{obj}</td>)}
</tr>
))}
</table>
);
I am retrieving the HTML object in another function which I am triggering on click of a button (found this code block on other SO pages):
const printData = (domElement) => {
var printContents = document.querySelector("table").innerHTML;
var originalContents = document.body.innerHTML;
document.body.innerHTML = printContents;
window.print();
document.body.innerHTML = originalContents;
};
There are 2 problems with this. 1 is that I lose all the HTML table elements upon clicking the print button, and it just becomes a long list without spaces. Second is that once I click it, all other elements on my page become unresponsive. I have attached a [sandbox][1] as well.
I'm new to React and javascript in general. Appreciate all the help!
UPDATE: Here's how I solved the problem: I found this solution based on a ton of other questions I found on SO:
const labelDataHTML = values =>
ReactDOMServer.renderToString(
<table id="dataTable" style={{ width: "100%" }}>
<caption>Labels</caption>
{_.chunk(values, 5).map((item, index) => {
return (
<tr className={`row`}>
{index % 5 !== 0
? item.map(obj => <td>{obj}</td>)
: item.map(obj => <td>{obj}</td>)
}
</tr>
);
})}
</table>
);
const PrintLabels = labelData => {
let domElement = labelDataHTML(labelData)
let windowInstance = window.open("");
windowInstance.document.write(domElement);
windowInstance.print();
windowInstance.close();
};
[1] : https://codesandbox.io/s/kind-cache-81qgu
Upvotes: 1
Views: 128
Reputation: 3441
For your first issue, you need to wrap your printContents
within html table
tag.
`<table>${printContents}</table>`
For your second problem, you need to create a window instance and open the print dialog in new window and then close the instance. You can refactor your function to something like this:
const printData = (domElement) => {
let printContents = document.querySelector("table").innerHTML;
let windowInstance= window.open("");
windowInstance.document.write(`<table>${printContents}</table>`);
windowInstance.print();
windowInstance.close();
};
Upvotes: 2
Reputation: 16344
You are temporarily changing the contents of the page in a way which I find to be a very hacky way to achive that.
A better way would be to hide every other element on the page only for print with css:
@media print {
body * {
visibility: hidden;
}
#dataTable,
#dataTable * {
visibility: visible;
}
#dataTable {
position: absolute;
left: 0;
top: 0;
}
}
Then you can simply print the table using:
window.print();
Upvotes: 0