@Override protected String doRender( List<ColumnData> cs, List<ModelData> rows, int startRow, int colCount, boolean stripe) { if (rows.size() < 1) { return ""; } String groupField = getGroupField(); int colIndex = cm.findColumnIndex(groupField); enableGrouping = groupField != null; if (!enableGrouping || isUpdating) { return super.doRender(cs, rows, startRow, colCount, stripe); } String gstyle = "width:" + getTotalWidth() + "px;"; String gidPrefix = grid.getId(); ColumnConfig cfg = cm.getColumn(colIndex); String prefix = showGroupName ? cfg.getHeader() + ": " : ""; GroupColumnData curGroup = null; String gid = null; List<GroupColumnData> groups = new ArrayList<GroupColumnData>(); for (int j = 0; j < rows.size(); j++) { ModelData model = (ModelData) rows.get(j); int rowIndex = (j + startRow); // the value for the group field Object gvalue = model.get(groupField); // the rendered group value String g = getGroup(gvalue, model, rowIndex, colIndex, ds); if (curGroup == null || !curGroup.group.equals(g)) { gid = getGroupId(gidPrefix, groupField, g); boolean isCollapsed = state.get(gid) != null ? !state.get(gid) : startCollapsed; String gcls = isCollapsed ? "x-grid-group-collapsed" : ""; curGroup = new GroupColumnData(); curGroup.group = g; curGroup.field = groupField; curGroup.gvalue = gvalue; curGroup.text = prefix + g; curGroup.groupId = gid; curGroup.startRow = rowIndex; curGroup.style = gstyle; curGroup.css = gcls; curGroup.models.add(model); groups.add(curGroup); } else { curGroup.models.add(model); } // model.set("_groupId", gid); } for (GroupColumnData group : groups) { if (groupRenderer != null) { String g = groupRenderer.render(group); if (g == null || g.equals("")) { g = " "; } group.group = g; } } StringBuilder buf = new StringBuilder(); for (int i = 0, len = groups.size(); i < len; i++) { GroupColumnData g = groups.get(i); doGroupStart(buf, g, cs, colCount); buf.append(super.doRender(cs, g.models, g.startRow, colCount, stripe)); doGroupEnd(buf, g, cs, colCount); } return buf.toString(); }