If you’re creating a line-of-business application, chances are pretty good that your users will need to print some data generated by your application.
As illustrated by the following code snippet, printing the contents of an Ext 4 panel is relatively straightforward. The basic algorithm is as follows:
- Instantiate a hidden iframe
- Dynamically copy the CSS of your app into the iFrame
- Dynamically copy the contents of the panel into the iFrame
- Call the window.print() method on the iFrame
- Destroy the iFrame
Ext.define('MyApp.view.override.Panel', { override: 'Ext.panel.Panel', print: function(pnl) { if (!pnl) { pnl = this; } // instantiate hidden iframe var iFrameId = "printerFrame"; var printFrame = Ext.get(iFrameId); if (printFrame == null) { printFrame = Ext.getBody().appendChild({ id: iFrameId, tag: 'iframe', cls: 'x-hidden', style: { display: "none" } }); } var cw = printFrame.dom.contentWindow; // instantiate application stylesheets in the hidden iframe var stylesheets = ""; for (var i = 0; i < document.styleSheets.length; i++) { stylesheets += Ext.String.format('<link rel="stylesheet" href="{0}" />', document.styleSheets[i].href); } // various style overrides stylesheets += ''.concat( "<style>", ".x-panel-body {overflow: visible !important;}", // experimental - page break after embedded panels // .x-panel {page-break-after: always; margin-top: 10px}", "</style>" ); // get the contents of the panel and remove hardcoded overflow properties var markup = pnl.getEl().dom.innerHTML; while (markup.indexOf('overflow: auto;') >= 0) { markup = markup.replace('overflow: auto;', ''); } var str = Ext.String.format('<html><head>{0}</head><body>{1}</body></html>',stylesheets,markup); // output to the iframe cw.document.open(); cw.document.write(str); cw.document.close(); // remove style attrib that has hardcoded height property cw.document.getElementsByTagName('DIV')[0].removeAttribute('style'); // print the iframe cw.print(); // destroy the iframe Ext.fly(iFrameId).destroy(); } });
Once you’ve loaded the override, you can simply call the panel.print() method.
Happy coding!
*********************
* UPDATED FOR EXTJS 6
*********************
Ext.define('MyApp.view.override.Panel', { override: 'Ext.panel.Panel', print: function(pnl) { if (!pnl) { pnl = this; } // instantiate hidden iframe var iFrameId = "printerFrame"; var printFrame = Ext.get(iFrameId); if (printFrame == null) { printFrame = Ext.getBody().appendChild({ id: iFrameId, tag: 'iframe', cls: 'x-hidden', style: { display: "none" } }); } var cw = printFrame.dom.contentWindow; // instantiate application stylesheets in the hidden iframe var stylesheets = ""; for (var i = 0; i < document.styleSheets.length; i++) { stylesheets += Ext.String.format('<link rel="stylesheet" href="{0}" />', document.styleSheets[i].href); } // various style overrides stylesheets += ''.concat( "<style>", ".x-panel-body {overflow: visible !important;}", // experimental - page break after embedded panels // .x-panel {page-break-after: always; margin-top: 10px}", "</style>" ); // get the contents of the panel and remove hardcoded overflow properties var markup = pnl.getEl().down('.x-autocontainer-innerCt').dom.innerHTML; while (markup.indexOf('overflow: auto;') >= 0) { markup = markup.replace('overflow: auto;', ''); } var str = Ext.String.format('<html><head>{0}</head><body><img src="resources/images/gabar-logo.gif">{1}</body></html>', '', markup); // output to the iframe cw.document.open(); cw.document.write(str); cw.document.close(); // remove style attrib that has hardcoded height property // cw.document.getElementsByTagName('DIV')[0].removeAttribute('style'); // print the iframe cw.print(); // destroy the iframe Ext.fly(iFrameId).destroy(); } });
Promising … I ll take a look at it.
Tested this version and got it working in Chrome not in FF or IE(11).
I got it working in FF, I postponed the destroy of the iframe in FF.
Is anyone else getting a “Print Preview Failed.” message?
Sorry for double posting but I’ve encountered the “Print Preview Failed” message whenever I have a Grid Panel or a Property Panel in my form.
The plugin doesn’t support grids. If you need to print a grid, see https://druckit.wordpress.com/2013/10/26/generate-an-excel-file-from-an-ext-js-4-grid/
Hi mate,
My name is Albert and I don’t write English very well.
Thanks for providing this implementation.
My problem is that I tried to print a GMapPanel but markers (icons) are not shown. Could you help me? Thank you very much!
I’ve never tried to print the contents of a GMapPanel, but presumably the icons aren’t printing because they’re implemented as a background-image. With Chrome and Safari you can add the CSS style “-webkit-print-color-adjust: exact;” to the element to force print the background color and/or image. There’s a couple of other hacks mentioned here:
http://stackoverflow.com/questions/6670151/how-can-i-force-browsers-to-print-background-images-in-css
Thanks for your quick response.
Who do I have to add this style? At GMapPanel? I’m a little lost 🙂
Can we have a callback on the print command to make sure if the user did click “Print” in print dialogue or just cancelled it?
Nope.
Pingback: ExtJS 4 – creating a callback for an override function for printing panel contents | 我爱源码网
Another question, it seems that it does not print checkboxes and radio buttons, have you had a workaround for this?
Users have to turn on printing background images in order to see checkboxes and radio buttons.
I am trying to print a long extjs5.1.x form(scrollabe form) using formPanel.print() command but nothing printing only empty page displayed
See the updated code snippet for Ext JS 6
In ExtJS6 the CSS from the Ext theme isn’t applied to the printed document. Is there something I’m missing? Or should I supply the css in a seperate css file?
That’s a feature, not s bug. This solution was designed to only output the text content from a panel, and not the Ext widgets. Therefore, you don’t need all of the overhead of the Ext styles.
Thanks for the reply and solution. So if I need formatting on the output I should supply css to the output. This just gives the plain text output (Font seems the system font on printing, something like Times New Roman).
Correct!
Thanks!
Hi,
I am trying to get the Print Preview of my Grid Panel, It prints out all contents but the Column header values are messed up. can you please help me to display the Header of all the columns on that. I tried your code as above. Do I need to add anything as part of the stylesheets?