I'm dealing with an ionic 5 app that was built as a web app. There's no mobile ponent to it.
I need to allow users to print a page. When I have a print button and associated with a function like the one below, it only prints the viewable area.
printPage() {
window.print();
}
Given the amount of content on the screen, I can tell that this document should be 2-3 pages long.
I see that there's a cordova-plugin-printer
plugin, but it's meant for printing from a mobile device.
What's the proper way to get the entire DOM printed?
I'm dealing with an ionic 5 app that was built as a web app. There's no mobile ponent to it.
I need to allow users to print a page. When I have a print button and associated with a function like the one below, it only prints the viewable area.
printPage() {
window.print();
}
Given the amount of content on the screen, I can tell that this document should be 2-3 pages long.
I see that there's a cordova-plugin-printer
plugin, but it's meant for printing from a mobile device.
What's the proper way to get the entire DOM printed?
Share Improve this question asked Jul 30, 2020 at 18:03 Ben DowneyBen Downey 2,6655 gold badges43 silver badges60 bronze badges 6-
window.print()
should launch the browser's print dialog, which allows the user to print the whole document, does it not? – Will Alexander Commented Jul 30, 2020 at 18:18 - It does not. I've tested in Chrome and Firefox. The dialog box indicates that it's only printing the viewable area. I suspect there's something ionic is doing here but I'm not sure. This should be a relatively straightforward mand. – Ben Downey Commented Jul 30, 2020 at 18:33
- There's a potentially useful answer here: stackoverflow./questions/10845621/… – Will Alexander Commented Jul 30, 2020 at 18:36
- Yeah, I found that in my googling but it had no effect. – Ben Downey Commented Jul 30, 2020 at 20:44
- Ionic has a lot of flexbox and overflow hidden CSS on its various page and toolbar and content ponents. I'm guessing a print media query would need to be added, and undo that CSS. Not sure what all of them are since it depends on what you have in your app. Hope that can help point you in the right direction – cjd82187 Commented Jul 31, 2020 at 1:25
3 Answers
Reset to default 4That might happen, because of a scrollable div, or something like that, nested in the body.
To get around this, you could manually select what to print by doing something like this answer from another StackOverflow question:
printPage() {
var mywindow = window.open('', 'PRINT', 'height=400,width=600');
mywindow.document.write('<html><head><title>' + document.title + '</title>');
mywindow.document.write('</head><body>');
mywindow.document.write(document.getElementById('#printArea').innerHTML);
mywindow.document.write('</body></html>');
mywindow.document.close(); // necessary for IE >= 10
mywindow.focus(); // necessary for IE >= 10*/
mywindow.print();
mywindow.close();
}
Link to the original answer: https://stackoverflow./a/2255438/9150652
I recently faced a similar situation and I ended up creating an angular ponent in my project, which is inspired by e-ngx-print.
The only limitation is that you will have to pass a *.css
file to this ponent for the section you want to print.
I have created a stackblitz for you, have a look and see if it's useful for you.
I tried first the sweet solution provided by @MauriceNino but noticed some throwback such as not preserving styles and fonts.
Therefore I opened an issue (that has been closed in favor of this issue) in the Ionic repo and developed the following workaround.
Basically, instead of copying the content in a popup, I clone the targeted node that contains the content at the body
root and remove it after print or when the use click the "cancel" button in the print modal.
export const print = ({element}: {element: Node}) => {
const body: HTMLBodyElement | null = document.querySelector('body');
if (!body) {
return;
}
const appRoot: HTMLElement | null = body.querySelector('app-root');
let node: Node | null | undefined = undefined;
window.addEventListener(
'afterprint',
() => {
if (node) {
body.removeChild(node);
}
appRoot?.classList.remove('hidden');
},
{once: true}
);
const onRender = async (_mutations: MutationRecord[], observer: MutationObserver) => {
observer.disconnect();
// Here you can do other things you need such as lazy loading content if you need too
appRoot?.classList.add('hidden');
window.print();
};
const docObserver: MutationObserver = new MutationObserver(onRender);
docObserver.observe(body, {childList: true, subtree: true});
node = body?.appendChild(element.cloneNode(true));
};
In addition, while printing, I hide the Ionic nodes. To do so I also defined following css (I am in a Stencil app that's why I target app-root
):
@media print {
app-root.hidden {
display: none;
}
}
Note the most beautiful hack but, does the job. Hopefully the issue will be solved soon.