3
votes

I have a grid with data similar to http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/array-grid.html, but using paged proxy similar to http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/paging.html.

I need to add a summary similar to http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/group-summary-grid.html, only 1 at the bottom of the grid. It must sum all data, not only data from current page.

I can make the DB query, no need Ext to sum the values. But how will I send the summary data to Ext.store and from store to grid?

3
Maybe it will be easier to add additional field to model that is bind to store(for example summary). Fill that field from json and show somewhere in grid ?Paweł Głowacz
Maybe, have you seen an example that I could use? Still, I need the visual effect of ExtJs.Grid summary, it can't just be another grid row.Hikari
@Hikari You can always use the SummaryRenderer property of Column from where you can return custom values and apply formatting.Avinash T.

3 Answers

2
votes

Handle this as example how you could implement.

This is how it looks like(of course it will be different data but you see the point): enter image description here

Lets see example of json(how it could be and how i understand your problem):

{
   "stats":[
      {
         "name":"Amount summary",
         "value":"2300"
      },
      {
         "name":"Mortgage",
         "value":"1100"
      }
   ],
   "success":true,
   "totalCount":2,
   "items":[
      {
         "Amount":"1000",
         "Delta":"3",
         "Mortgage":"500"
      },{
         "Amount":"1300",
         "Delta":"4",
         "Mortgage":"600"
      }
   ]
}

Model:

Ext.define('Application.model.MyModel', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'Amount',
        type: 'string'
    },{
        name: 'Delta',
        type: 'string'
    },{
        name: 'Mortgage',
        type: 'string'
    }]
});

Store:

var writer = new Ext.data.JsonWriter({
    type: 'json',
    encode: false,
    listful: true,
    writeAllFields: true,
    returnJson: true
});

var reader = new Ext.data.JsonReader({
    type: 'json',
    totalProperty: 'totalCount',
    rootProperty: 'items',
    successProperty: 'success'
});

var proxy = new Ext.data.HttpProxy({
    reader: reader,
    writer: writer,
    type: 'ajax',
    url: 'urlForJson',
    headers: {
        'Content-Type': 'application/json; charset=UTF-8'
    }
});

Ext.define('Application.store.MyStore', {
    extend  : 'Ext.data.Store',
    storeId : 'MyStore',
    model   : 'Application.model.MyModel',
    autoLoad: false,
    autoSync: true,
    proxy:proxy
});

Lets define controller that is going to handle our summary/statistics:

Ext.define('Application.controller.SummaryController', {
    extend: 'Ext.app.Controller',
    refs: [
        {
            selector: 'summaryPanel',
            ref: 'summaryPanel'
        }
    ],
    init: function () {
        var controller = this;
        controller.listen({
            controller: {
                '*': {
                    addSummary: 'addSummary'
                }
            }
        });
    },

    /**
     * Add summary.
     */
    addSummary: function addSummary(summary) {
        var controller = this;
        var summaryPanel= controller.getSummaryPanel();
        summaryPanel.removeAll();
        Ext.Object.each(stats, function(property, stat){
            var labelFieldName = new Ext.form.Label({
                text: stat.name+': '
            });
            var labelFieldValue = new Ext.form.Label({
                text: stat.value+'  ',
                cls: 'bold-item'
            });
            summaryPanel.items.add(labelFieldName);
            summaryPanel.items.add(labelFieldValue);
        });
        summaryPanel.up('window').doLayout();
    }
});

And this is our SummaryPanel:

Ext.define('Application.view.SummaryPanel', {
    extend: 'Ext.Panel',
    alias: 'widget.summaryPanel',
    xtype: 'summaryPanel',
    layout: 'anchor',
    bodyStyle: 'padding: 5px 5px;',
    items: []
});

In next step we are going to load our data to grid and after that we will fill our SummaryPanel with statistics/summary:

Ext.define('Application.controller.GridController', {
    extend: 'Ext.app.Controller',
    init: function () {
        var controller = this;

        controller.control({
            'gridControlPanel': {
                'afterrender': function () {
                    controller.loadStore();
                }
            }
        })
    },
    loadStore: function () {
        var controller = this;
        var store = Ext.getStore('Application.store.MyStore');
        store.load({
            callback: function (records, operation, success) {
                var data = Ext.JSON.decode(operation._response.responseText);

                if (!Ext.isEmpty(data.stats)) {
                    //After loading data, make statistics.
                    controller.fireEvent('addSummary', data.stats);//This event is handled by SummaryController
                }
            }
        });
    }
});

And this UI that cover all above:

Ext.define('Application.view.GridWindow', {
    extend: 'Ext.window.Window',
    alias: 'widget.gridWindow',
    xtype: 'gridWindow',
    addMode: false,
    autoShow: true,
    width: 1200,
    height: 700,
    resizable: true,
    layout: 'fit',
    items: [{
        xtype: 'grid',
        store: 'Application.store.MyStore',
        dockedItems: [{
            xtype: 'pagingtoolbar',
            dock: 'bottom',
            store: 'Application.store.MyStore',
            displayInfo: true
        }]
    }],
    dockedItems: [{
        xtype: 'summaryPanel'//This is our summary panel that will show your summarize.
    }]
});
1
votes

You can use the ExtJS Grid feature -

Ext.grid.feature.Summary

to display summary at the bottom of grid.

Here is the simple example to answer your question - https://fiddle.sencha.com/#fiddle/tq7

In example, i have directly used the summary object in summaryRenderer of column.

1
votes

So, for a summary row, you've got the Summary feature. You can stick it in the bottom of your grid with the dock: 'bottom' option. And, finally, to use remotely computed data for the summary, you've got the remoteRoot option. Voilà.

... Except the thing is apparently half baked and remoteRoot is really only used with grouping. Oops. "No need to handle the simple case", they must have thought.

Here's an override that fills the missing part you're needing (fiddle):

Ext.define('Ext.grid.feature.RemoteSummary', {
    override: 'Ext.grid.feature.Summary',

    // adds 'remote' summary type
    getSummary: function (store, type, field, group) {
        if (type === 'remote') {
            return this.getRemoteSummaryRecord(store).get(field);
        } else {
            return this.callParent(arguments);
        }
    },

    // helper for our custom summary type, mainly copied from:
    // http://docs.sencha.com/extjs/4.2.3/source/AbstractSummary.html#Ext-grid-feature-AbstractSummary-method-generateSummaryData
    getRemoteSummaryRecord: function(store) {
        if (!this.remoteSummaryRecord) {
            var reader = store.proxy.reader,
                remoteRoot = this.remoteRoot,
                root;

            if (remoteRoot && reader.rawData) {
                root = reader.root;
                reader.root = remoteRoot;
                reader.buildExtractors(true);

                this.remoteSummaryRecord = reader.read(reader.rawData).records[0];

                if (!reader.convertRecordData) {
                    reader.buildExtractors();
                }

                reader.root = root;
                reader.buildExtractors(true);
            }
        }
        if (!this.remoteSummaryRecord) {
            this.remoteSummaryRecord = store.model.create({});
        }
        return this.remoteSummaryRecord;
    },

    // ensure our remoteSummaryRecord stays fresh
    onStoreUpdate: function() {
        delete this.remoteSummaryRecord;
        return this.callParent(arguments);
    }
});

You would then use it like this:

Ext.create('Ext.grid.Panel', {
    features: [{
        ftype: 'summary',
        remoteRoot: 'summary', // summary key in the server response
        dock: 'bottom'
    }],
    columns: [{
        text: 'Age',
        dataIndex: 'age',
        summaryType: 'remote'
    }]
    //...
});

With some data of this form:

{
    "summary": {
        "age": 95,
    },
    "items": [/*...*/]
}

(And, yes, summing ages makes a lot of sense)