Observing print events
There’s an Angular application which needs a different layout for its component when the user asks for a printed version. Yes, you can plain the media
queries, but they’re not enough in certain cases. That’s why I had to find a different way to archieve the goal.
On print requests, the browser is emitting two events: beforeprint
and afterprint
. I thought that listening to those ones could be a possible solution: the application can alter its view on beforeprint
, to restore the regular approach on the next afterprint
. So I’ve build this small helper function.
export const observePrintEvents = (win: Window): Observable<'beforeprint' | 'afterprint'> =>
merge(
fromEvent(win, 'beforeprint').pipe(mapTo<Event, 'beforeprint'>('beforeprint')),
fromEvent(win, 'afterprint').pipe(mapTo<Event, 'afterprint'>('afterprint'))
);
To make it easier, I also introduced another helper on the top of the previous one.
export const printMode = (win: Window) => observePrintEvents(win)
.pipe(map(event => event === 'beforeprint'), startWith(false));
Things like these can be successfully used in a template (through async
pipe) to match the expectation. Think about an *ngIf
directive which will show or hide a certain component for print-layout only.
But there’s a problem: window.print
method we call to trigger the print programmatically is blocking the JavaScript execution. That’s not an issue while using the browser menu or the shortcuts (e.g. CTRL + P
on Windows), but it is when triggering the print within an event handler (like listening to a button click). So, that’s the definitive way of raising a print request!
export const printWindow = (win: Window) => {
win.dispatchEvent(new Event('beforeprint'));
setTimeout(() => { win.print(); });
};
The main idea is to programmatically dispatch a beforeprint
event and then putting a window.print
in the event queue. In this way the page will have the chance to adapt before being blocked for the printing process. You can have a look here for a working example. Hope you’ll enjoy!