People using ExtJs/Ext.Net/Coolite might be aware of the GroupingSummary plugin, for the GridPanel that allows you to group GridPanel rows on a particular field, and then display columns summaries for each set of grouped rows independently (see here and here for ExtJs & Ext.Net/Coolite examples respectively).
A handy plugin I must agree, but in my case, I wanted to display summaries for columns of GridPanels without any grouping. As I googled out and asked for help on Coolite forums regarding this, I came across this and this thread on ExtJs forums, as well as this thread on Coolite forums. On an initial observation, I thought of adopting either the GridTotals plugin posted by the wonderful ExtJs community member, Animal here, or the code posted by Coolite core member, vlad here.
However, on closer inspection, I thought vlad’s solution was not optimal because it added an extra record to the GridPanel’s store for the summary row, which might cause problems when you are processing the Store’s data in your code, unless you explicitly take care and ignore the summary row from your processing.
So, I decided to go with Animal’s GridTotals plugin. But when I used it in my code, I had a series of javascript errors. Confused, when I dug into the code, I noticed that Ext.Net GridPanel’s CommandColumns were causing issues. So, I had to adapt Animal’s code for use in Ext.Net GridPanel. Here’s the adpated code, which works under both ExtJs as well as Ext.Net/Coolite perfectly:
{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }Ext.ux.GridTotals = Ext.extend(Ext.util.Observable, {
constructor: function(config) {
config = config || {};
this.showHeaderInTotals = config.showHeaderInTotals;
this.divideRowHeightBy2 = config.divideRowHeightBy2;
Ext.ux.GridTotals.superclass.constructor.call(this, config);
},
init: function(g) {
var v = g.getView();
this.grid = g;
this.store = g.getStore();
//Need to override GridView’s findRow to not consider total’s row as normal grid row.
v.findRow = function(el) {
if (!el) {
return false;
}
if (this.fly(el).findParent(‘.x-grid-total-row’, this.rowSelectorDepth)) {
return (false);
} else {
return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
}
}
g.cls = (g.cls || ”) + ‘x-grid3-simple-totals’;
g.gridTotals = this;
this.store.on({
reconfigure: { fn: this.onGridReconfigure, scope: this },
add: { fn: this.updateTotals, scope: this },
remove: { fn: this.updateTotals, scope: this },
update: { fn: this.updateTotals, scope: this },
datachanged: { fn: this.updateTotals, scope: this }
});
v.onLayout = v.onLayout.createSequence(this.onLayout, this);
v.initElements = v.initElements.createSequence(this.initElements, this);
v.onAllColumnWidthsUpdated = v.onAllColumnWidthsUpdated.createSequence(this.onLayout, this);
v.onColumnWidthUpdated = v.onColumnWidthUpdated.createSequence(this.onLayout, this);
},
initElements: function() {
var v = this.grid.getView();
v.scroller.on(‘scroll’, function() {
v.totalsRow.setStyle({
left: -v.scroller.dom.scrollLeft + ‘px’
});
});
},
onLayout: function() {
this.updateTotals();
this.fixScrollerPosition();
},
fixScrollerPosition: function() {
var v = this.grid.getView();
var bottomScrollbarWidth = v.scroller.getHeight() – v.scroller.dom.clientHeight;
v.totalsRow.setStyle({
bottom: bottomScrollbarWidth + ‘px’,
width: Math.min(v.mainBody.getWidth(), v.scroller.dom.clientWidth) + ‘px’
});
//Reduce the height of the scroller to create spce for totals row to avoid overlapping.
var height = (this.divideRowHeightBy2 !== false) ? v.totalsRow.dom.clientHeight / 2 : v.totalsRow.dom.clientHeight;
v.scroller.setHeight(v.scroller.dom.clientHeight – height);
},
getTotals: function() {
var v = this.grid.getView();
var cs = v.getColumnData();
var totals = new Array(cs.length);
var store = v.grid.store;
var fields = store.recordType.prototype.fields;
var columns = v.cm.config;
for (var i = 0, l = v.grid.store.getCount(); i < l; i++) {
var rec = store.getAt(i);
for (var c = 0, nc = cs.length; c < nc; c++) {
var f = cs.name;
var t = !Ext.isEmpty(f) ? fields.get(f).type : ”;
if (columns.totalsText) {
totals = columns.totalsText;
//} else if (t.type == ‘int’ || t.type == ‘float’) {
} else if (columns.summaryType) {
var v = rec.get(f);
if (Ext.isDefined(totals)) {
switch (columns.summaryType) {
case ‘sum’:
totals += v;
break;
case ‘min’:
if (v < totals) {
totals = v;
}
break;
case ‘max’:
if (v > totals) {
totals = v;
}
break;
}
} else {
switch (columns.summaryType) {
case ‘count’:
totals = l;
break;
default:
totals = v;
break;
}
}
}
}
}
return (totals);
},
getRenderedTotals: function() {
var v = this.grid.getView();
var totals = this.getTotals();
var cs = v.getColumnData();
var store = v.grid.store;
var columns = v.cm.config;
var cells = ”, p = {};
for (var c = 0, nc = cs.length, last = nc – 1; c < nc; c++) {
if (columns.roundToPlaces) {
totals = Math.roundToPlaces(totals, columns.roundToPlaces);
}
if (this.showHeaderInTotals) {
if (Ext.isEmpty(totals)) {
totals = ‘ ’;
} else {
totals += ‘: ‘ + cs.scope.header;
}
}
var v = Ext.isDefined(totals) ? totals : ”;
if (columns.summaryType && columns.summaryRenderer) {
var renderer = columns.summaryRenderer;
if (Ext.isString(renderer)) {
renderer = Ext.util.Format[renderer];
}
totals = renderer(v, p, undefined, undefined, c, store);
}
}
return (totals);
},
updateTotals: function() {
if (!this.grid.rendered) {
return;
}
var v = this.grid.getView();
if (!v.totalsRow) {
v.mainWrap.setStyle(‘position’, ‘relative’);
v.totalsRow = v.templates.row.append(v.mainWrap, {
tstyle: ‘width:’ + v.mainBody.getWidth(),
cells: ”
}, true);
v.totalsRow.addClass(‘x-grid-total-row’);
v.totalsTr = v.totalsRow.child(‘tr’).dom;
}
var totals = this.getRenderedTotals();
var cs = v.getColumnData();
var cells = ”, p = {};
for (var c = 0, nc = cs.length, last = nc – 1; c < nc; c++) {
p.id = cs.id;
p.style = cs.style;
p.css = c == 0 ? ‘x-grid3-cell-first ‘ : (c == last ? ‘x-grid3-cell-last ‘ : ”);
cells += v.templates.cell.apply(Ext.apply({
value: totals
}, cs));
}
while (v.totalsTr.hasChildNodes()) {
v.totalsTr.removeChild(v.totalsTr.lastChild);
}
Ext.DomHelper.insertHtml(‘afterBegin’, v.totalsTr, cells);
},
onGridReconfigure: Ext.emptyFn
});
{/syntaxhighlighter}
I have made a couple of fixes and enhancements to the Animal’s plugin.
- As said earlier, it was adapted for Ext.Net GridPanel, by taking the CommandColumns into consideration.
- In my case, I needed to maintain dynamic running totals for the columns. Thus I needed to update the column summaries when data in the GridPanel’s store changed. So, I have registered additional listeners for the GridPanel’s store to upate column summaries as you can see here:
{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }this.store.on({
reconfigure: { fn: this.onGridReconfigure, scope: this },
add: { fn: this.updateTotals, scope: v },
remove: { fn: this.updateTotals, scope: v },
update: { fn: this.updateTotals, scope: v },
datachanged: { fn: this.updateTotals, scope: v }
});{/syntaxhighlighter} - For integer and float columns, I needed to display column summaries as sum of values for the rows. However, for other columns (String etc.), I needed to display static text as the summary. So, I enhanced the Plugin to support this. Now, you can specify any text as totalsText custom config option for any GridPanel column like below:
<ext:Column DataIndex="fullName" Header="Passenger"> <CustomConfig> <ext:ConfigItem Name="totalsText" Value="Total" Mode="Value" /> </CustomConfig> </ext:Column>
If this config option is specified for a column, the corresponding value for the totalsText column config option would be used in the summary row.
- A very important point to remember about this plugin is that it displays summaries for only int or float columns, and it is important to specify the data type for the Store field explicitly for which you want column summaries as the sum of the column values. See the example below:
<ext:RecordField Name="tax1" Type="Float" DefaultValue="0" /> <ext:RecordField Name="tax2" Type="Float" DefaultValue="0" />
This plugin natively supports only sum of column values for summaries (or the static totalsText option as specified above). But it should not be too difficult adapting it to support average or any other other column summary calculation. If anyone needs help doing so, please let me know.
And the last important point, do not forget to also include the following css in the page somewhere:
{syntaxhighlighter brush: css;fontsize: 100; first-line: 1; }.x-grid3-simple-totals .x-grid3-row-last {
margin-bottom: 21px;
}
.x-grid3-simple-totals .x-grid-total-row {
position: absolute;
left: 0;
bottom: 15px;
background: #F9F9F9 url(../../resources/images/default/grid/grid3-hrow.gif);
}
.x-grid3-simple-totals .x-grid-total-row td {
border-left: 1px solid #EEEEEE;
border-right: 1px solid #D0D0D0;
padding-left: 0px;
padding-right: 0px;
}{/syntaxhighlighter}
My last couple of blog entires (including this one) have been adaptations of other’s code, rather than code written from the scratch myself. I again fully acknowledge Animal’s code that I have adapted for my needs.
Here’s a demonstration of this plugin:
UPDATE:
- Sep 16, 2010 – Reversed the order of checking of field data types and presence of totalsText for a column to give more preference to totalsText if specified.
- May 27, 2011 – Updated code to support better rendering of column totals.
Added live sample for the demo.
The complete code including the html file for the above sample and js and css resource files for the plugin are attached below.
Hi
i tried with this sample code but i could not fill my requirement . since i reruire not onlg total of column ,i require minimum and maximum valuse in that column
Please can you provide a sample code for it
Hi, if I use your plugin, I get the following error, everytime i click on summary row cell:
this.getRow(row) is undefined
Hi,
Look into this blazing fast code. I have a situation where the grid contains many many rows.
what i did was to scan the fields for columns that i need to compute and looping only them and only if i found data to loop on.
also i did some optimization with variables declarations.
I’ve been trying to use your plugin but I had the following errors :
this.mainWrap is undefined
[Break on this error] if (!this.totalsRow) {… if (!this.totalsHasStaticText) {
GridTotals.js (ligne 79)
columns is undefined
[Break on this error] for (var c …m) // cannot have both features
GridTotals.js (ligne 81)
There must be something wrong with my grid declaration but I cant’ figure it out, do you have an idea?
Here is my grid declaration. If you need more information, I’d be happy to give it to you.
Also, I would like my summary line to be on top of the grid and not at the bottom, do you think it can be done easily?
var grid_issCurrentHour = new Ext.grid.GridPanel
(
{
id : ‘grid_issCurrentHour’,
store : ga_storeIssCurrentHour,
columns :
[
{
header : ‘Acquereur’,
width : 80,
sortable : true,
dataIndex : ‘acq’,
renderer : acqRenderer
}
,
{
header : ‘Success’,
width : 100,
sortable : true,
dataIndex : ‘success’
}
,
{
header : ‘Fail’,
width : 100,
sortable : true,
dataIndex : ‘fail’
}
,
{
header : ‘Total’,
width : 100,
sortable : true,
dataIndex : ‘total’
}
,
{
header : ‘Rate%’,
width : 100,
sortable : true,
dataIndex : ‘rate’,
renderer : rateRenderer,
id : ‘rate’
}
],
stripeRows : true,
style : ‘margin:auto;width:100%’,
title : ‘ATM Issuer Current Hour’,
height : 400,
plugins : [ new Ext.ux.GridTotals() ],
autoExpandColumn : ‘rate’
}
);
Thanks, I’m getting there slowly
Now I’ve got these errors
this.mainWrap is undefined
this.mainWrap.setStyle(‘position’, ‘relative’); GridTotals.js (ligne 55) columns is undefined
if (columns[c].totalsText) { GridTotals.js (ligne 73
Just a request:
When doing writeups like this, could you please post a working example?
( ya know, like the examples bit in Ext site )
Tends to make life easier for people trying to get it working 🙂
Still useful though, tyvm
Hi and thanx for publishing this, just what I was looking for!
I just have one issue and it’s when clicking on the row containing the totals, I get en error in Ext, I think it has to do with the grid trying to resolve the cell we create for the display, to track rowIndex.
I’ve spend a couple of hours trying to solve this whithout any success. Can you or anybody verify that this is an issue not only for me. And most of all, is there a sulotion for this?
Many thanks
Pete
I was just trying out all the summary plugins when I came across your post. Very good writeup. Saved me atleast 2-3 hours. Thanks.
Hi rahul,
I am also in a look out for a plugin for Grid row summary.
But i am having a hard time in creating a plugin in .Net so as i can use it in GridPanel Control like this
<Plugins>
<ext:GridSummaryRow runat=”server”>
</ext:GridSummaryRow>
</Plugins>
i have created a class for this GridSummaryRow but it is my lack of through knowledge in .net that is preventing me from understanding how to create a plugin for this.
My GridSummaryRow class is as follows
I have created this class by copy pasting existing code from Ext.Net control library. Can you please help me understand how to actually create a plugin.
Hi rahul,
Thanks for this powerfull plugin ! It’s what i need for my development.
But i have a problem with the cell’s width… you can see my grid here : http://imageshack.us/photo/my-images/534/feuilledepointageavecsu.png/, you see that the width of the total row isn’t the same that the other row, it’s because i make a mistake in the configuration ? Or because i use e editor grid ? Or is there a specific action to do that correctly ?
Thanks for your reply !
//width: Math.min(v.mainBody.getWidth(), v.scroller.dom.clientWidth) + ‘px’
width: v.mainBody.getWidth() + ‘px’
Thats how I think I solved it.
Rahul,
I would like to implement our curreny formatter in your script but I didn’t achieve. Could you please give me an advice to accomplish such a thing?
Here is currency formatter :
Ext.onReady(function() {
if(Ext.util.Format) {
if(!Ext.util.Format.CurrencyFactory) {
Ext.util.Format.CurrencyFactory = function(hasSpace, dp, dSeperator, tSeperator, symbol, rightPosition) {
return function(n) {
var spaceText = hasSpace ? ” ” : “”;
dp = Math.abs(dp) + 1 ? dp : 2;
dSeperator = dSeperator || “.”;
tSeperator = tSeperator || “,”;
symbol = symbol || “TL”;
rightPosition = rightPosition || false;
var m = /(\d+)(?:(\.\d+)|)/.exec(n + “”),
x = m[1].length > 3 ? m[1].length % 3 : 0;
var v = (n < 0? ‘-‘ : ”)
+ (x ? m[1].substr(0, x) + tSeperator : “”)
+ m[1].substr(x).replace(/(\d{3})(?=\d)/g, “$1” + tSeperator)
+ (dp ? dSeperator + (+m[2] || 0).toFixed(dp).substr(2) : “”);
return rightPosition ? v+spaceText+symbol : symbol+spaceText+v;
};
};
}
}
});
I can format a currency field like this :
renderer: Ext.util.Format.CurrencyFactory(true, 2, “,”, “.”, “TL”, true)
But, when I want to use with column summary like below, the script ( currency formatter ) throws an error:
summaryRenderer: Ext.util.Format.CurrencyFactory(true, 2, “,”, “.”, “TL”, true)
m is null
x = m[1].length > 3 ? m[1].length % 3 : 0;
Hello,
When i try to do a sum of one column without roundToPlace for example:
Result for sum of :
760844.14
719751.50
1821660.55
0
————–
3302256.1900000004
Now when i try to do a sum with roundToPlace:
<ext:ConfigItem Name=”roundToPlaces” Value=”2″ Mode=”Value” />
Result for sum of :
760844.14
719751.50
1821660.55
0
————–
3.30225619e+24 (I should be getting 3,302,256.19)
Hi!
I have LockingGridView and summary row. If I lock one column then the summary row moves itself to right of border (locking border).
I want it to stay on the left as it it. How can I do that?
Thank you very much
I have a grid with the field Quantity, Size, and a calculated field of TotalQuantity (Quantity* Size). My grid is bound to this object. I have a summaryRow for the TotalQuantity column. The summary row doesn’t show my sum correctly .
If I change the Quantity in the grid on the fly, the TotalQuantity gets updated, but the summary row doesn’t, unless I ‘refresh’ it (i.e. I sort by that column). Ideas on what I might be missing? Do i have do something to manually force a summary row update?
Thank you very much for answer 🙂
Hi, and great work Rahoul!
If you try to resize a column, the total bubble up…something about scroller.
Regards
as well as in the previous post, if GridPanel have many columns we need horizontal scroller. Summary row not scrolling 🙁
Regards
Hi Rahul,
You’re plugin has helped me a ton (and I’ve learned a lot about ExtJS modifying it!). Thanks so muvh for putting it out there.
One trouble I’m having though, is that in IE8 the Summary Row covers up the last row of real data. I’ve mucked around with the CSS and with the height settings in fixScrollerPosition() but to no avail.
I am using ExtJS 3.4, and using your plugin on a EditorGridPanel – don’t know if this could be the issue. (I do not observe the issue in FireFox).
If you have any suggestions that would be great.
Hi Rahul,
I have added a couple of features!
1. defined and used a property totalsPosition taking ‘top’ or ‘bottom’
usage:
new Ext.ux.GridTotals({totalsPosition: ‘top’}); // or ‘bottom’
2. ability to define summaryType : ‘custom’ and define summaryMethod, so that it is called while iterating through each record. This could useful in situations where your summary is neither a fixed summaryText nor any of add, count, etc. eg Say in Summary Row in Company column you want to say “Found 8 companies having price more than $50.00”.
usage (say in the html you defined) :
// create the Grid
grid = new Ext.grid.GridPanel({
store: store,
plugins: gridTotalsPlugin,
columns: [
{
id: ‘company’,
header: ‘Company’,
width: 160,
sortable: true,
dataIndex: ‘company’,
‘summaryType’: ‘custom’,
‘summaryMethod’ : function(runningValue, fieldValue, record, store, recordIndex){
if(runningValue == null || isNaN(runningValue)){
runningValue = 0;
}
var theCount = parseInt(runningValue);
if(recordIndex < store.getCount()-1){
if(record.price > 50.00){
theCount++;
return theCount;
}else{
return theCount;
}
}else{ // reached the last row
if(record.price > 0.9){
theCount++;
}
return “Found ” + theCount + ” records greater than 50.00″;
}
}
},
{
header: ‘Price’,
….
I am new to ExtJS, but know javascript in general.
Home the custom summary method is useful !!
My changed code is not getting attached. I will try to paste it in my reply to this post.
this is the full source code of the modified plugin with totalsPosition and custom summaryMethod
highlighted code is the new lines.
Ext.ux.GridTotals = Ext.extend(Ext.util.Observable, {
constructor: function(config) {
config = config || {};
this.showHeaderInTotals = config.showHeaderInTotals;
this.divideRowHeightBy2 = config.divideRowHeightBy2;
this.totalsPosition = config.totalsPosition;
if(this.totalsPosition==null){
this.totalsPosition = ‘bottom’;
}
this.totalsPosition = this.totalsPosition.toLowerCase();
if(this.totalsPosition!=’bottom’ && this.totalsPosition!=’top’){
this.totalsPosition = ‘bottom’;
}
Ext.ux.GridTotals.superclass.constructor.call(this, config);
},
init: function(g) {
var v = g.getView();
this.grid = g;
this.store = g.getStore();
//Need to override GridView’s findRow to not consider total’s row as normal grid row.
v.findRow = function(el) {
if (!el) {
return false;
}
if (this.fly(el).findParent(‘.x-grid-total-row’, this.rowSelectorDepth)) {
return (false);
} else {
return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
}
}
g.cls = (g.cls || ”) + ‘x-grid3-simple-totals’;
g.gridTotals = this;
this.store.on({
reconfigure: { fn: this.onGridReconfigure, scope: this },
add: { fn: this.updateTotals, scope: this },
remove: { fn: this.updateTotals, scope: this },
update: { fn: this.updateTotals, scope: this },
datachanged: { fn: this.updateTotals, scope: this }
});
v.onLayout = v.onLayout.createSequence(this.onLayout, this);
v.initElements = v.initElements.createSequence(this.initElements, this);
v.onAllColumnWidthsUpdated = v.onAllColumnWidthsUpdated.createSequence(this.onLayout, this);
v.onColumnWidthUpdated = v.onColumnWidthUpdated.createSequence(this.onLayout, this);
},
initElements: function() {
var v = this.grid.getView();
v.scroller.on(‘scroll’, function() {
v.totalsRow.setStyle({
left: -v.scroller.dom.scrollLeft + ‘px’
});
});
},
onLayout: function() {
this.updateTotals();
this.fixScrollerPosition();
},
fixScrollerPosition: function() {
var v = this.grid.getView();
var bottomScrollbarWidth = v.scroller.getHeight() – v.scroller.dom.clientHeight;
v.totalsRow.setStyle({
bottom: bottomScrollbarWidth + ‘px’,
width: Math.min(v.mainBody.getWidth(), v.scroller.dom.clientWidth) + ‘px’
});
//Reduce the height of the scroller to create spce for totals row to avoid overlapping.
var height = (this.divideRowHeightBy2 !== false) ? v.totalsRow.dom.clientHeight / 2 : v.totalsRow.dom.clientHeight;
v.scroller.setHeight(v.scroller.dom.clientHeight – height);
},
getTotals: function() {
var v = this.grid.getView();
var cs = v.getColumnData();
var totals = new Array(cs.length);
var store = v.grid.store;
var fields = store.recordType.prototype.fields;
var columns = v.cm.config;
for (var i = 0, l = v.grid.store.getCount(); i < l; i++) {
var rec = store.getAt(i);
for (var c = 0, nc = cs.length; c < nc; c++) {
var f = cs[c].name;
var t = !Ext.isEmpty(f) ? fields.get(f).type : ”;
if (columns[c].totalsText) {
totals[c] = columns[c].totalsText;
//} else if (t.type == ‘int’ || t.type == ‘float’) {
} else if (columns[c].summaryType) {
var v = rec.get(f);
if (Ext.isDefined(totals[c])) {
switch (columns[c].summaryType) {
case ‘sum’:
totals[c] += v;
break;
case ‘min’:
if (v < totals[c]) {
totals[c] = v;
}
break;
case ‘max’:
if (v > totals[c]) {
totals[c] = v;
}
break;
case ‘custom’:
if(columns[c].summaryMethod){
totals[c] = columns[c].summaryMethod(totals[c], v, rec.data, store, i);
}
break;
}
} else {
switch (columns[c].summaryType) {
case ‘count’:
totals[c] = l;
break;
case ‘custom’:
if(columns[c].summaryMethod){
totals[c] = columns[c].summaryMethod(null, v, rec.data, store, i);
}
break;
default:
totals[c] = v;
break;
}
}
}
}
}
return (totals);
},
getRenderedTotals: function() {
var v = this.grid.getView();
var totals = this.getTotals();
var cs = v.getColumnData();
var store = v.grid.store;
var columns = v.cm.config;
var cells = ”, p = {};
for (var c = 0, nc = cs.length, last = nc – 1; c < nc; c++) {
if (columns[c].roundToPlaces) {
totals[c] = Math.roundToPlaces(totals[c], columns[c].roundToPlaces);
}
if (this.showHeaderInTotals) {
if (Ext.isEmpty(totals[c])) {
totals[c] = ‘ ’;
} else {
totals[c] += ‘: ‘ + cs[c].scope.header;
}
}
var v = Ext.isDefined(totals[c]) ? totals[c] : ”;
if (columns[c].summaryType && columns[c].summaryRenderer) {
var renderer = columns[c].summaryRenderer;
if (Ext.isString(renderer)) {
renderer = Ext.util.Format[renderer];
}
totals[c] = renderer(v, p, undefined, undefined, c, store);
}
}
return (totals);
},
updateTotals: function() {
if (!this.grid.rendered) {
return;
}
var v = this.grid.getView();
if (!v.totalsRow) {
v.mainWrap.setStyle(‘position’, ‘relative’);
if(this.totalsPosition!=’top’){
v.totalsRow = v.templates.row.append(v.mainWrap, {
tstyle: ‘width:’ + v.mainBody.getWidth(),
cells: ”
}, true);
}else{
v.totalsRow = v.templates.row.insertAfter( v.mainHd, v.mainWrap, {
tstyle: ‘width:’ + v.mainBody.getWidth(),
cells: ”
}, true);
}
v.totalsRow.addClass(‘x-grid-total-row’);
v.totalsTr = v.totalsRow.child(‘tr’).dom;
}
var totals = this.getRenderedTotals();
var cs = v.getColumnData();
var cells = ”, p = {};
for (var c = 0, nc = cs.length, last = nc – 1; c < nc; c++) {
p.id = cs[c].id;
p.style = cs[c].style;
p.css = c == 0 ? ‘x-grid3-cell-first ‘ : (c == last ? ‘x-grid3-cell-last ‘ : ”);
cells += v.templates.cell.apply(Ext.apply({
value: totals[c]
}, cs[c]));
}
while (v.totalsTr.hasChildNodes()) {
v.totalsTr.removeChild(v.totalsTr.lastChild);
}
Ext.DomHelper.insertHtml(‘afterBegin’, v.totalsTr, cells);
},
onGridReconfigure: Ext.emptyFn
});
//Utility Method for rounding values.
Math.roundToPlaces = function(num, dec) {
var result = Math.round(Math.round(num * Math.pow(10, dec + 1)) / Math.pow(10, 1)) / Math.pow(10, dec);
return result;
}
Hi rahul,
Thank you so much for your plugin. In my case it works like a charm until I have a requirement from my customer to freeze some columns on the left of the grid similar to excel. I’ve tried to apply the Locking Grid Column with Grouping extension to do the requirement but the last summary row of the grid from the plugin was disappeared when they worked together.
Any suggestion?
Thanks in advance,
Tuan Ngo
thanks yaar,,, your plugin really helped in need ..
cheers
looks great Rahul!!
not used to the plugins/extensions but this makes things clearer.
for anyone – I have a quick (stupid?) question for anyone out there – what is ‘afterBegin’ supposed to be set to?
I have a to which I have my grid renderTo set.
looks great Rahul!!
for anyone who can help:
I have a quick/noob question for anyone out there – what is
‘afterBegin’ supposed to be set to?
I have a to which I have my grid renderTo set.
I am not sure I entirely understand your question Raja. “afterBegin” is supposed to inject the html for the summary row on the page, it has nothing to do with grid’s renderTo config which you can use to render grid in a specific area of your web page (which you should only use if you are not using ExtJs layouts).