You are hereBlogs / rahul's blog / Ext.Net/ExtJs - GridPanel columns summary plugin (without Grouping)

Ext.Net/ExtJs - GridPanel columns summary plugin (without Grouping)


rahul's picture

By rahul - Posted on 21 April 2010

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:

 

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[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;
                        }
                    } else {
                        switch (columns[c].summaryType) {
                            case 'count':
                                totals[c] = l;
                                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] = '&nbsp;';
                } 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');
            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[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
});

I have made a couple of fixes and enhancements to the Animal's plugin.

  1. As said earlier, it was adapted for Ext.Net GridPanel, by taking the CommandColumns into consideration.
  2. 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:

    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 }
    });
     
  3. 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.

  4. 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:

.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;
}

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.

 

AttachmentSize
gridpanel-totals-without-grouping.htm5.83 KB
Ext.ux.GridTotals.js7.35 KB
Ext.ux.GridTotals.css454 bytes

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

rahul's picture

Hi sekhar, the code attached with the blog post should be easily modifiable to fulfill min/max value requirement for the column. I will try to post the code if possible, but I am afraid my current schedule would not allow me to post something immediately.

There was something of this sort available on ExtJs forums. Try googling out, you might well find it there...

Hi, if I use your plugin, I get the following error, everytime i click on summary row cell:

this.getRow(row) is undefined

ext-all.js (line 2369)
Do you have any idea, why?
Other problem:
var columns = this.cm.columns;
columns are always null.
Do you have any example of using your plugin, obviously I'm doing something wrong.
Thank you, Simon
rahul's picture

Hi Simon, I was able to reproduce your first issue. Clicking on the summary row indeed generates that error. I will try to figure out a solution for this issue. However, that might take sometime depending upon my schedule. In the meantime, you can probably seek help on this ExtJs forum thread.

For the second issue (related to columns), you did not specify the context where you tried to access this (this.cm.columns). If this referred to the plugin object itself, then obviously the plugin does not has the column model, you need to access cm via a reference to the owner grid, grid.cm.columns.

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.

// OPTIONS
//---------------------------------------
// when using this plug-in attached to a grid, you can set these options:
//
// on a column object in the options of the grid:
//
// totalsText - string - a string to render inside the cell. can be HTML.
// totalsSum  - boolean - true to calculate sum in the client
//

Ext.ux.GridTotals = Ext.extend(Ext.util.Observable, {

init: function (g) {
g.cls = (g.cls || '') + 'x-grid3-simple-totals';

var v = g.getView();
g.gridTotals = this;

this.grid = g;

this.store = g.getStore();
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 }
});

v.updateTotals = this.updateTotals;
v.fixScrollerPosition = this.fixScrollerPosition;
v.onLayout = v.onLayout.createSequence(this.onLayout);
v.initElements = v.initElements.createSequence(this.initElements);
v.onAllColumnWidthsUpdated = v.onAllColumnWidthsUpdated.createSequence(this.onLayout);
v.onColumnWidthUpdated = v.onColumnWidthUpdated.createSequence(this.onLayout);

v.tmStore = this.store;
},

initElements: function () {
var me = this;
this.scroller.on('scroll'function () {
me.totalsRow.setStyle({
left: -me.scroller.dom.scrollLeft + 'px'
});
});
},

onLayout: function () {
this.updateTotals();
this.fixScrollerPosition();
},

fixScrollerPosition: function () {
var bottomScrollbarWidth = this.scroller.getHeight() - this.scroller.dom.clientHeight;
this.totalsRow.setStyle({
bottom: bottomScrollbarWidth + 'px',
width: Math.min(this.mainBody.getWidth(), this.scroller.dom.clientWidth) + 'px'
});
},

updateTotals: function () {

//
// build the total row
//

if (!this.totalsRow) {
this.mainWrap.setStyle('position''relative');
this.totalsRow = this.templates.row.append(this.mainWrap, {
tstyle: 'width:' + this.mainBody.getWidth(),
cells: ''
}, true);
this.totalsRow.addClass('x-grid-total-row');
this.totalsTr = this.totalsRow.child('tr').dom;
}

if (!this.totalsHasStaticText) {
var verifyFeatures = function (v) {
var a_static = new Array();
var a_sum = new Array();

var cs = v.getColumnData();
var csLength = cs.length;
var columns = v.cm.columns;

// loop on all columns to find needed features
for (var c = 0; c < csLength; c++) {
var col = columns[c];
if (col.totalsText)
a_static.push(c);
else if (col.totalsSum) // cannot have both features
a_sum.push(c);
}

return {
hasStaticText: a_static.length > 0,
staticIndices: a_static,
hasSum: a_sum.length > 0,
sumIndices: a_sum
};
};

var features = verifyFeatures(this);
this.totalsHasStaticText = features.hasStaticText;
this.totalsStaticIndices = features.staticIndices;
this.totalsHasSum = features.hasSum;
this.totalsSumIndices = features.sumIndices;
}


var cs = this.getColumnData();
var csLength = cs.length;
var totals = new Array(csLength);
var fields = this.tmStore.recordType.prototype.fields;
var columns = this.cm.columns;
var count = this.tmStore.getCount();
var count2 = this.totalsSumIndices.length;

var rec, i, c, col, f, t, v, x;

//
// loop for static text
//
if (this.totalsHasStaticText) {
for (c = 0; c < count2; c++) {
col = columns[this.totalsStaticIndices[c]];
if (col.totalsText)
totals[this.totalsStaticIndices[c]] = col.totalsText;
}
}

//
// loop for client data calculations
//
if (this.totalsHasSum) {
for (i = 0; i < count; i++) {
rec = this.tmStore.getAt(i);
for (c = 0; c < count2; c++) {
x = this.totalsSumIndices[c];
col = columns[x];
if (col.totalsSum) {
f = cs[x].name;
t = !Ext.isEmpty(f) ? fields.get(f).type : '';
if (t.type == 'int' || t.type == 'float') {
v = rec.get(f);
if (Ext.isDefined(totals[x]))
totals[x] += v;
else
totals[x] = v;
}
}
}
}
}

//
// build the cells HTML
//

var cells = '', p = {};
for (c = 0, last = csLength - 1; c < csLength; c++) {
p.id = cs[c].id;
p.style = cs[c].style;
p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
v = Ext.isDefined(totals[c]) ? totals[c] : '';
cells += this.templates.cell.apply(Ext.apply({
value: cs[c].renderer(v, p, undefined, undefined, c, this.tmStore)
}, cs[c]));
}

//
// append the cells to the summary row
//

// remove current cells
while (this.totalsTr.hasChildNodes())
this.totalsTr.removeChild(this.totalsTr.lastChild);
Ext.DomHelper.insertHtml('afterBegin'this.totalsTr, cells);
},

onGridReconfigure: Ext.emptyFn
});
rahul's picture

Hi Jacob, thanks for sharing your code. I could not get time to test it currently, but anything that improves performance is certainly good.

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'
   }
);

rahul's picture

Hi Laurent, it appears to me tat you are using Jacob Dvir's code posted in the comment. I have not really tested it, but can you please try the code from the main post itself?

Regarding your other issue of having the totals row at the top, I think it should require a change in line 56 of the original code in the post. Instead of appending, you would need to insert the row. This is just a guess, but I think a change in line 56 together with some other minor changes should be all that's required.

Thanks, you were right, I was using the other plugin.
Now I have a different error :
config is undefined

 

rahul's picture

Hi Laurent, can you please use this instead while trying to instantize the plugin:

new Ext.ux.GridTotals({showHeaderInTotals:true}

Pass a true or false value for the parameter depending upon whether or not you want the Column headers to be shown in the totals.(If in doubt, test with both true and false values for this paremeter).

Thanks, I'm getting there slowly Smile

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

rahul's picture

Hmmm... It might have to do with the ExtJs version. I am currently using it successfully in multiple applications running on ExtJs 3.3.0. I believe it should work fine for any ExtJs 3.x version. Can you please confirm your ExtJs version??

I'm using ext-3.3.0...

Maybe there's a file I forgot to include ?

What is this mainWrap property anyway ? I can't find it on the api documentation

rahul's picture

I do not believe this could be caused by failure to include a file (you must be including ext-all.js anyway). I am not sure why is this error occurring??

Regarding mainWrap, well I really haven't came across the documentation either. But from what I see, many ExtJs components have wrapper element (just div which wraps whole component markup). 'mainWrap' references that div. You might get a better answer for mainWrap on ExtJs forums.

Hi, I managed to make it work (I don't know what the problem was).

The only problem remaining is how to display the total line at the top of the grid and not at the bottom. I tried to do as you said, ie changing the line 56 of your plugin.

I tried to replace 'append' with 'insertFirst' but then the summary line goes on top of the header. I should use insertAfter or insertBefore but I don't know how to specify the first argument for this function. Do you have an idea ?

Thanks very much for everything

rahul's picture

Hi Laurent, would you like to share with us what issue you were having and how you resolved it, so that other users of the blog can benefit?

Regarding showing at the top after headers, here's what you should use:

  1. Change Line 56 in script to following:
    this.totalsRow = this.templates.row.insertAfter(this.mainHd, {
  2. In css for the plugin, remove the following 2 lines:
    position: absolute;
    bottom: 15px

I have tested it now, and the above 2 steps show the totals row where you want it.

My problem was the definition of the column model.

It should have been

new Ext.grid.ColumnModel
(
        {
            columns:
            [
                {
                    header          :   lz_header,

...

instead of

new Ext.grid.ColumnModel
(
        {
               header          :   lz_header,

...

hence the error "columns is undefined"

As for the other error "this.mainWrap.setStyle('position', 'relative'); GridTotals.js (ligne 55)"

it suddenly disappear after I erased the browser's history !

 

Anyway, the changes I've made to your plugin are :

            this.totalsRow = this.templates.row.append(this.mainWrap, {
replaced by

            this.totalsRow = this.templates.row.insertAfter(
                this.mainHd,
                this.mainWrap, {

Also, I have changed the code so that you could have an average or a count instead of a sum in the total line.

Thus, I added these properties in the column model

- tt can be 'sum', 'count' or 'average'

- tt_precision : used only if tt is average

In the plugin, the lines in red have been added :

                var t = !Ext.isEmpty(f) ? fields.get(f).type : '';
                var tt = Ext.isDefined(columns[c].tt) ? columns[c].tt : 'sum';
                if (columns[c].totalsText) {
                    totals[c] = columns[c].totalsText;
                } else if (t.type == 'int' || t.type == 'float') {
                    var v = rec.get(f);
                    if (Ext.isDefined(totals[c])) {
                        totals[c] += v;
                    } else {
                        totals[c] = v;
                    }
                    if (i == l - 1)
                    {
                        if (tt == 'average')
                        {
                            tt_precision = Ext.isDefined(columns[c].tt_precision) ? columns[c].tt_precision : 2;
                            var avg = totals[c] / this.grid.store.getCount();
                            totals[c] = avg.toFixed(tt_precision);
                        }
                        else if (tt == 'count')
                        {
                            totals[c] = this.grid.store.getCount();
                        }
                    }

                    if (this.showHeaderInTotals && (i == l - 1)) {

Thank you again

 

rahul's picture

Hi Laurent, good to know that the plugin works for you, and thanks for sharing your enhancements.

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

rahul's picture

Thanks for your feedback Alex. I realized that working example tends to help the readers better and hence my subequent blog posts have been with working examples where ever suitable. I have been trying to re-visit my earlier blog posts but haven't been getting enough time.

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

rahul's picture

Hi Pete, sorry for the delay in the response. I was able to reproduce the issue. And here's the fix for it. Add the following libes to the top of init method for the plugin:

 

        init: function(g) {
            //Need to override GridView's findRow to not consider total's row as normal grid row.
            g.getView().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);
                }
            }

// Other code from the main blog post
            var v = g.getView();
            this.grid = g;
            this.store = g.getStore();
.....................

We override GridPanel View's findRow method to ensure that our totals row is not considered a regular GridPanel row.

 

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.

Please, please, please... i will be very thankful
Regards,
Huzefa

 

AttachmentSize
GridSummaryRow.cs 1.29 KB
rahul's picture

Hi huzefa, sorry for the delayed reply.

Did you add your class to Ext.Net's source itself or to your App_Code or custom assembly?
In case you added it to Ext.Net, did you recompile and updated the dll to your bin folder? Also did you set your js resource build action to EmbeddedResource in the assembly?

If you added it to App_Code or custom assembly, then did you <% Register %> the namespace and assembly? Also the code would need changes then.

The simplest way is NOT to try creating an server-side Ext.Net plugin class. You can well use it in custom config section for your gridpanel. e.g.

<ext:GridPanel runat="server">
    <CustomConfig>
        <ext:ConfigItem Name="plugins" Value="new Ext.ux.GridTotals({/*Your config options here*/})" />
    </CustomConfig>
</ext:GridPanel>

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 !

rahul's picture

Hi Quentin, on a couple of occasions I have myself seen that the total row did not align up perfectly with other rows in my grids. However that was not serious enough and I did not take care to debug it. I will need to see whether its a issue with the plugin or your configuration. Can you put up a live example somewhere??

When I use it varying sizes of columns this issue becomes prominent.  Each column width is exactly 2px shorter. 

            //width: Math.min(v.mainBody.getWidth(), v.scroller.dom.clientWidth) + 'px'
            width: v.mainBody.getWidth() + 'px'

Thats how I think I solved it. 

rahul's picture

Okay, thanks Nat for sharing your solution.

Post new comment

The content of this field is kept private and will not be shown publicly.
Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.

Recent comments