说明:客户要求Grid下方有合计功能,截图如下
实现代码如下:
Ext.ns('Ext.ux.grid'); var debug = !false; Ext.ux.grid.GridSummary = function(config) { Ext.apply(this, config); }; Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, { init: function(grid) { this.grid = grid; this.cm = grid.getColumnModel(); this.view = grid.getView(); var v = this.view; // override GridView's onLayout() method v.onLayout = this.onLayout; v.afterMethod('render', this.refreshSummary, this); v.afterMethod('refresh', this.refreshSummary, this); //v.afterMethod('syncScroll', this.syncSummaryScroll, this); v.afterMethod('onColumnWidthUpdated', this.doWidth, this); v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); // update summary row on store's add/remove/clear/update events grid.store.on({ add: this.refreshSummary, remove: this.refreshSummary, clear: this.refreshSummary, update: this.refreshSummary, scope: this }); if (!this.rowTpl) { this.rowTpl = new Ext.Template('<div style="overflow-x:hidden;" class="x-grid3-summary-row ,x-grid3-gridsummary-row-offset" >', '<table class="x-grid3-summary-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">', '<tbody><tr>{cells}</tr></tbody>', '</table>', '</div>'); this.rowTpl.disableFormats = true; } this.rowTpl.compile(); if (!this.cellTpl) { this.cellTpl = new Ext.Template( '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} x-selectable {css}" style="{style}" tabIndex="0" {cellAttr}>', '<div class="x-grid3-cell-inner x-grid3-col-{id}" {attr}>{value}</div>', '</td>'); this.cellTpl.disableFormats = true; } this.cellTpl.compile(); }, calculate: function(rs, cm) { var data = {}, cfg = cm.config; // loop through all columns in ColumnModel for (var i = 0, len = cfg.length; i < len; i++) { var cf = cfg[i], // get column's configuration cname = cf.dataIndex; // get column dataIndex // initialise grid summary row data for the current column being // worked on data[cname] = 0; if (cf.summaryType) { for (var j = 0, jlen = rs.length; j < jlen; j++) { var r = rs[j]; // get a single Record data[cname] =toDecimal(Ext.ux.grid.GridSummary.Calculations[cf.summaryType](r.get(cname), r, cname, data, j)); } } } return data; }, onLayout: function(vw, vh) { if (Ext.type(vh) != 'number') { // handles grid's height:'auto' config return; } // note: this method is scoped to the GridView if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) { // readjust gridview's height only if grid summary row is visible this.scroller.setHeight(vh - this.summary.getHeight()); } }, syncSummaryScroll: function() { var mb = this.view.scroller.dom; this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore) this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // alert(this.view.summaryWrap.dom.scrollLeft); }, doWidth: function(col, w, tw) { var s = this.view.summary.dom; s.firstChild.style.width = tw; s.firstChild.rows[0].childNodes[col].style.width = w; }, doAllWidths: function(ws, tw) { var s = this.view.summary.dom, wlen = ws.length; s.firstChild.style.width = tw; var cells = s.firstChild.rows[0].childNodes; for (var j = 0; j < wlen; j++) { cells[j].style.width = ws[j]; } }, doHidden: function(col, hidden, tw) { var s = this.view.summary.dom, display = hidden ? 'none': ''; s.firstChild.style.width = tw; s.firstChild.rows[0].childNodes[col].style.display = display; }, renderSummary: function(o, cs, cm) { cs = cs || this.view.getColumnData(); var cfg = cm.config, buf = [], last = cs.length - 1; for (var i = 0, len = cs.length; i < len; i++) { var c = cs[i], cf = cfg[i], p = {}; p.id = c.id; p.style = c.style; p.css = i == 0 ? 'x-grid3-cell-first ': (i == last ? 'x-grid3-cell-last ': ''); var ds = this.grid.store; if ((cf.summaryType || cf.summaryRenderer) && ds.getTotalCount() > 0) { p.value = (cf.summaryRenderer || c.renderer)(o.gridData[c.name], p, o); } else { p.value = ''; } if (p.value == undefined || p.value === "") p.value = " "; buf[buf.length] = this.cellTpl.apply(p); } return this.rowTpl.apply({ tstyle: '' + this.view.getTotalWidth() + ';', cells: buf.join('') }); }, refreshSummary: function() { var g = this.grid, ds = g.store, cs = this.view.getColumnData(), cm = this.cm, rs = ds.getRange(), data = this.calculate(rs, cm), buf = this.renderSummary({ gridData: data }, cs, cm); if (!this.view.summaryWrap) { this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, { tag: 'div', cls: 'x-grid3-gridsummary-row-inner' }, true); } else { this.view.summary.remove(); } this.view.summary = this.view.summaryWrap.update(buf).first(); this.view.scroller.setStyle('overflow-x', 'hidden'); var view2 = this.view; this.view.summary.setStyle('overflow', 'auto');//解决滚动条滚动问题和页面刷新滚动条回到初始位置问题。 this.view.summary.dom.scrollLeft = this.view.scroller.dom.scrollLeft;//解决滚动条滚动问题和页面刷新滚动条回到初始位置问题。 this.view.summary.on("scroll", function() { view2.scroller.dom.scrollLeft = view2.summary.dom.scrollLeft }); }, toggleSummary: function(visible) { // true to display summary row var el = this.grid.getGridEl(); if (el) { if (visible === undefined) { visible = el.hasClass('x-grid-hide-gridsummary'); } el[visible ? 'removeClass': 'addClass']('x-grid-hide-gridsummary'); this.view.layout(); // readjust gridview height } }, getSummaryNode: function() { return this.view.summary } }); Ext.reg('gridsummary', Ext.ux.grid.GridSummary); Ext.ux.grid.GridSummary.Calculations = { sum: function(v, record, colName, data, rowIdx) { return data[colName] + toDecimal(Ext.num(v, 0)); }, count: function(v, record, colName, data, rowIdx) { return rowIdx + 1; }, max: function(v, record, colName, data, rowIdx) { return Math.max(Ext.num(v, 0), data[colName]); }, min: function(v, record, colName, data, rowIdx) { return Math.min(Ext.num(v, 0), data[colName]); }, average: function(v, record, colName, data, rowIdx) { var t = data[colName] + Ext.num(v, 0), count = record.store.getCount(); return rowIdx == count - 1 ? (t / count) : t; }, total:function(){ return "\u5408\u8ba1"; } } //保留两位小数 //功能:将浮点数四舍五入,取小数点后2位 function toDecimal(x) { var f = parseFloat(x); if (isNaN(f)) { return; } f = Math.floor(x*100)/100; return f; }
3、使用如下:
var summary = new Ext.ux.grid.GridSummary(); //声明
this.gridPanel = new Ext.grid.GridPanel({
id: "PlanBookAllGrid",
region: "center",
stripeRows: true,
tbar: this.topbar,
store: this.store,
columnLines: true,
"100%",
trackMouseOver: true,
disableSelection: false,
loadMask: true,
cm: a,
sm: b,
plugins: [this.rowActions, summary],//加入plugins中
viewConfig: {
forceFit: false,
enableRowBody: false,
showPreview: false
},
bbar: new HT.PagingBar({
store: this.store
})
});
var a = new Ext.grid.ColumnModel({
columns: [b, new Ext.grid.RowNumberer({
header: "序号",
35
}), {
header: "mainid",
dataIndex: "mainid",
hideable: false,
hidden: true
},
{
header: "runid",
dataIndex: "runid",
hideable: false,
hidden: true
},
{
header: "年计划项目号",
dataIndex: "planProjectNu",
summaryType: "total"
},
{
header: "培训班名称",
dataIndex: "trainingClassName"
},
{
header: "培训类别一",
dataIndex: "trainingMainType"
},
{
header: "培训类别二",
dataIndex: "trainingSonType"
},
{
header: "培训类别三",
dataIndex: "trainingGrandsonType"
},
{
header: "培训开始时间",
dataIndex: "trainingStartTime",
renderer: function(v2) {
return AppUtil.formateDate(v2);
}
},
{
header: "培训结束时间",
dataIndex: "trainingEndTime",
renderer: function(v2) {
return AppUtil.formateDate(v2);
}
},
{
header: "月度",
dataIndex: "monthly"
},
{
header: "班级数",
dataIndex: "classNumber",
summaryType: 'sum' //需要合计的Column中添加summaryType
},
{
header: "课时",
dataIndex: "forsecastClassTime",
summaryType: 'sum'
},