Ext JS 4: Printing the contents of an Ext.Panel

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.

printpanel

As illustrated by the following code snippet, printing the contents of an Ext 4 panel is relatively straightforward. The basic algorithm is as follows:

  1. Instantiate a hidden iframe
  2. Dynamically copy the CSS of your app into the iFrame
  3. Dynamically copy the contents of the panel into the iFrame
  4. Call the window.print() method on the iFrame
  5. 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!

14 thoughts on “Ext JS 4: Printing the contents of an Ext.Panel

  1. Razgriz

    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.

    Reply
  2. Albert

    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!

    Reply
    1. sdrucker Post author

      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

      Reply
      1. Albert

        Thanks for your quick response.
        Who do I have to add this style? At GMapPanel? I’m a little lost 🙂

  3. Razgriz

    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?

    Reply
  4. Pingback: ExtJS 4 – creating a callback for an override function for printing panel contents | 我爱源码网

  5. Razgriz

    Another question, it seems that it does not print checkboxes and radio buttons, have you had a workaround for this?

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s