View Full Version : Ext.ux.Printer including row body

9 Aug 2010, 7:41 AM
Ed Spencer created an awesome library for printing grids and trees. Check it out at Ext.ux.Printer (http://edspencer.net/2009/07/extuxprinter-printing-for-any-ext.html).

The thing is that my app contains a lot of grids that either use row bodies or the RowExpander grid plugin for extra data. I tweaked the GridPanelRenderer so that it would print the extra body if visible. Below is the new code.

* @class Ext.ux.Printer.GridPanelRenderer
* @extends Ext.ux.Printer.BaseRenderer
* @author Ed Spencer
* Helper class to easily print the contents of a grid. Will open a new window with a table where the first row
* contains the headings from your column model, and with a row for each item in your grid's store. When formatted
* with appropriate CSS it should look very similar to a default grid. If renderers are specified in your column
* model, they will be used in creating the table. Override headerTpl and bodyTpl to change how the markup is generated.
* @author pscrawford Enhanced to include the row body.
* @constructor
* @param {Object} config
Ext.ux.Printer.GridPanelRenderer = Ext.extend(Ext.ux.Printer.BaseRenderer, {
* @property bodyTpl
* @type Ext.XTemplate
* The XTemplate used to create each row. This is used inside the 'print' function to build another XTemplate, to which the data
* are then applied (see the escaped dataIndex attribute here - this ends up as "{dataIndex}")
bodyTpl: new Ext.XTemplate(
'<tpl for=".">',

* @property headerTpl
* @type Ext.XTemplate
* The XTemplate used to create the headings row. By default this just uses <th> elements, override to provide your own
,headerTpl: new Ext.XTemplate(
'<tpl for=".">',

* @property rowBodySelector
* @type String
,rowBodySelector: '.x-grid3-row-body'

* Generates the body HTML for the grid
* @param {Ext.grid.GridPanel} grid The grid to print
,generateBody: function(grid) {
var columns = this.getColumns(grid)
//use the headerTpl and bodyTpl XTemplates to create the main XTemplate below
,headings = this.headerTpl.apply(columns)
,body = this.bodyTpl.apply(columns)
,table = [
'<tpl for=".">{1}',
'<tpl if="rowBody">',
'<tr><td colspan={2}>{rowBody}</td></tr>',

return String.format(table, headings, body, columns.length);
} //eof generateBody

* Prepares data from the grid for use in the XTemplate
* @param {Ext.grid.GridPanel} grid The grid panel
* @return {Array} Data suitable for use in the XTemplate
,prepareData: function(grid) {
//We generate an XTemplate here by using 2 intermediary XTemplates - one to create the header,
//the other to create the body (see the escaped {} below)
var columns = this.getColumns(grid)
//build a useable array of store data for the XTemplate
,data = []
,ds = grid.getStore()
,view = grid.getView()
,hasRowBody = view.enableRowBody
,sel = this.rowBodySelector

ds.each(function(item, rowIndex) {
var convertedData = {};

//apply renderers from column model
Ext.iterate(item.data, function(key, value) {
Ext.each(columns, function(column) {
if (column.dataIndex == key) {
convertedData[key] = column.renderer ? column.renderer.call(column.scope || this, value, {}, item) : value;
return false;
}, this);

rb = null;
if (hasRowBody){
row = view.getRow(rowIndex);
if (row){
el = Ext.fly(row).child(sel);
if (el && el.isVisible()){
rb = el.dom.innerHTML;
convertedData['rowBody'] = rb;


return data;
} //eof prepareData

* Returns the array of columns from a grid
* @param {Ext.grid.GridPanel} grid The grid to get columns from
* @return {Array} The array of grid columns
,getColumns: function(grid) {
var columns = [];

Ext.each(grid.getColumnModel().config, function(col) {
if (!col.hidden && col.dataIndex){
}, this);

return columns;
} //eof getColumns


Ext.ux.Printer.registerRenderer('grid', Ext.ux.Printer.GridPanelRenderer);

Thanks Ed for such an extensible library!

10 Aug 2010, 9:44 AM
Is posible live example?


4 Feb 2013, 10:36 AM
Thanks for doing all the work for me ;-)