title: ExtJS - grouping grid results
body: <p>I have a grid containing store.
  I'm not able to group the rows in that grid for some reason.</p>
  
  <p>my grid looks something like this (can't upload a picture since i don't have enough reputation):</p>
  
  <pre><code>+-------------+---------------+--------------+---------+
  | userName    | sipUserName   | osIdentifier | ...     |
  +-------------+---------------+--------------+---------+
  |           1 | 1             | 123456       |       1 |
  |           1 | 2             | 654321       |       1 |
  |           3 | 3             | 654321       |       2 |
  |           4 | 4             | 654321       |       1 |
  +-------------+---------------+--------------+---------+
  </code></pre>
  
  <p>And i want to aggregate the results by the 'userName' column.</p>
  
  <p>The grid contains the store is:</p>
  
  <pre><code>UsersGrid = function(config) {
  
  var serviceName = 'getSystemInfo?groupName=';
  serviceName+=groupName;
  
  
  this.store = new RestStore({serviceName: serviceName, fields:[
      'userName', 
      'sipUserName',
      'osIdentifier',
      'majorVersion',
      'minorVersion',
      'patchVersion',
      'platformIdentifier'
  ] ,  groupField : 'userName'
  });
  
  
  this.store.on('beforeload', function(store, options){
      var params = Ext.getCmp('UsersPanel').getParams();
      store.baseParams=params;
  }, this);
  
  
  UsersGrid.superclass.constructor.call(this, {
      selModel:new Ext.grid.RowSelectionModel({singleSelect:true}),
      features: [
         {
          ftype: 'grouping',
          groupHeaderTpl: [
            'ss'
          ],
          hideGroupedHeader: true,
          startCollapsed: false
         }
      ],
  
      columns:[
           {header:'User Name', dataIndex:'userName', width:100, sortable:true}
          ,{header:'Sip User Name', dataIndex:'sipUserName', width:100, sortable:true}
          ,{header:'Os Identifier', dataIndex:'osIdentifier', width:100, sortable:true}
          ,{header:'Major Version', dataIndex:'majorVersion', width:100, sortable:true }
          ,{header:'Minor Version', dataIndex:'minorVersion', width:100, sortable:true }
          ,{header:'Patch Version', dataIndex:'patchVersion', width:100, sortable:true }
          ,{header:'Platform', dataIndex:'platformIdentifier', width:100, sortable:true }
      ],
  
      bbar:new Ext.PagingToolbar({store:this.store, pageSize:50, displayInfo:true})
  });
  Ext.apply(this, config);
  
  this.store.paging = this.getBottomToolbar();
  
  };
  Ext.extend(UsersGrid, Ext.grid.GridPanel, {}); 
  </code></pre>
  
  <p>The store I'm using is:</p>
  
  <pre><code>// default REST store
  RestStore = function(cfg) {
  var url = cfg.url || apiUrl;
  var idProperty = cfg.idProperty || 'id';
  if (!cfg.url &amp;&amp; cfg.serviceName) url=url+cfg.serviceName;
  var groupField = cfg.groupField;
  
  RestStore.superclass.constructor.call(this, {
      restful:true,
      proxy: new Ext.data.HttpProxy({
          url:url,
          listeners: {
              beforewrite:function(writer,action,rs,params){
                  params.jsonData=params.jsonData.entities;
              },
              beforeload: {scope:this, fn:function(ds, params){
                  var webQuery={};
                  var page=1;  if (params.start) page = Math.ceil(params.start / params.limit);
  
                  if (this.paging) {
                      webQuery.numberOrItemsPerRequest = this.paging.pageSize;
                      webQuery.requestNumber = page;
                  }
  
                  webQuery.likeCriterions = params.likeCriterions;
                  webQuery.simpleCriterions = params.simpleCriterions;
                  webQuery.simpleDateCriterions = params.simpleDateCriterions;
                  webQuery.inCriterions = params.inCriterions;
                  webQuery.orders = params.orders;
  
  
                  if (!isEmpty(webQuery)) params.webQuery=webQuery;
              }}
          }
          ,api:{
              read:{url:url}
  
          }
  
      }),
      reader: new Ext.data.JsonReader(
          {totalProperty:'filter.totalEntities', root:'entities', idProperty:idProperty, messageProperty:'message', successProperty:'success', groupField:groupField},
          cfg.fields
      )
      ,writer: new Ext.data.JsonWriter({encode:true, writeAllFields:true})
      ,listeners: {
          exception: function(proxy, type, action, op, res){
              var d={};
              if (!res.message &amp;&amp; res.responseText) { d=Ext.decode(res.responseText); res.message=d.errorMessage; }
              Ext.Msg.show({title:'Error'+(d.errorCode?' #'+d.errorCode:''), msg:(res.message||'error'), icon:Ext.MessageBox.ERROR, buttons:Ext.Msg.OK, minWidth:600});
          },
          load:function(ds, rec, op){ // set totalLength
              if (ds.reader.jsonData.filter &amp;&amp; ds.reader.jsonData.filter.totalEntities) ds.totalLength = ds.reader.jsonData.filter.totalEntities;
          }
      }
  });
  };
  Ext.extend(RestStore, Ext.data.Store);
  
  
  Ext.override(Ext.data.JsonReader,{
  
  readRecords : function(o){
      this.jsonData = o;
      if(o.metaData) this.onMetaChange(o.metaData);
  
      var s = this.meta, Record = this.recordType, f = Record.prototype.fields, fi = f.items, fl = f.length, v;
  
      if(s.successProperty){
          v = this.getSuccess(o);
          if(v === false || v === 'false') success = false;
      }
  
      if(s.totalProperty){
          v = parseInt(this.getTotal(o), 10);
          if(!isNaN(v)) totalRecords = v;
      }
  
      if(s.groupField){
          groupField = s.groupField;
      }
  
      var root = this.getRoot(o);
      if (!root) { // no records returned
          return {success:success, records:[], totalRecords:0, message:o.message};
      }
      var c = root.length, totalRecords = c, success = true;
  
      return {
          success : success,
          records : this.extractData(root, true), 
          totalRecords : totalRecords,
          groupField : groupField,
          remoteGroup : true
      };
  }
  });
  </code></pre>
  
  <p>Can anyone help in figuring out what is the problem?</p>