在Extjs的使用过程中跟panel有关系的大控件用的最多的的除了formPanel之外,就是GridPanel用得最多了,也就是各种表格。而在使用GridPanel的时候主要用到了显示出来有四种形式的表格,分别和ColumnModel、GridView、SelectionModel、Store等有关。下面就分别介绍这几种GridPanel,
关于grid,还有很多有趣的操作:如选择某一行,获得当前行的内容,并显示到不同的文档内,则使用其中的‘rowselect’方法,或者selectchange等方法,其具体用法如下:
this._selection.panel = this; //选择改变时候赋值 brotherPanel.getSelectionModel().on('rowselect', function (sm, rowIndx, r) { sm.panel._textFieldDeviceName.setValue(r.data.deviceName); sm.panel._textFieldDeviceEnglishName.setValue(r.data.englishName); sm.panel._textFieldDeviceUnitPrice.setValue(r.data.unitPrice / 1000000 + '万'); sm.panel._textAreaConfiguration.setValue(r.data.configuration); sm.panel._textAreaMainSpec.setValue(r.data.mainSpec); sm.panel._textAreaAccessorySpec.setValue(r.data.accessorySpec); })//研究Extjs越来越发现,同时也越来越感叹原生的js大师是多么牛掰,那都是大神一级的人物啊!
1、一般的GridPanel
定义一个GridPanel主要包括数据来源(Store)、ColumnModel、行单击事件('celldblclick')、分页甚至查询等,定义方式还是按照继承(constructor)的形式。
Ipms.projects.ProjectGridPanel = function (id, projectStore, title, iconCls, isPart, queryParams) { //fields this._projectStore = projectStore; this._projectStore.grid = this; var isCollege = Ipms.currentLoginLog.user.isCollege; //controls this._selections = new Ext.grid.RowSelectionModel();//定义行选择模式,当需要的表格列表有checkbox时就需要用Ext.grid.CheckboxSelectionModel,
此时有三个属性:checkOnly:是否只能通过点击checkbox列进行选择,默认为false
sortable:是否允许checkbox列排序,默认为false
width:checkbox列的宽度,默认为20 this._columnModel = new Ipms.projects.ProjectGridPanel_ColumnModel();//定义列模式 this._filters = new Ipms.projects.ProjectGridPanel_GridFilters();//定义筛选器 this._toolbar = new Ipms.projects.ProjectGridPanel_ToolBar(this._projectStore, this._selections, id, this);//定义topBar,其中放按钮等
this._view = new Ext.grid.GridView({ forceFit: true,//是否强制调整表格列宽以适用表格的整体宽度,防止出现水平滚动条,默认为false ignoreAdd: true, emptyText: '没有满足条件的项目'//没有数据时显示的提示文本,另外gridView有getRowClass配置项,如在下面另一个页面中定义的
getRowClass: function (record, rowIndex, rowParams, store) {//这里就是将不同状态的条目用不同的颜色区分出来
if (record.data.currentState != state &&expertApply.isNew()) {return 'my_row_Grey';}
}); //constructor Ipms.projects.ProjectGridPanel.superclass.constructor.call(this, { id: id,//设置当前表格的id,标识唯一性,也可以不用 stateful: true, store: this._projectStore,//定义数据集,一个表格必须要有数据集 sm: this._selections,//表格的选择模式,默认为Ext.grid.RowSelectionModel enableColumnHide: true,//是否允许通过标题中的上下文菜单隐藏列,默认为true enableColumnMove: true,//是否允许拖放列,默认为true border: false,//是否显示边框 title: title,//表格的名称 enableDragDrop: true,//可拖动 iconCls: iconCls,//定义图标 region: 'center', closable: true,//可以关闭 loadMask: true,//加载数九时显示loadMask plugins: this._filters,//添加的附件、这里用于筛选 colModel: this._columnModel,//表格的列模式,渲染表格时必须设置;配置项表格列模式的也可为配置数组,可自动创建ColumnModel列模式 view: this._view,//定义视图,内部定义表格显示的方式 tbar: this._toolbar,//定义表格上面的topBar,其中放各种按钮,添加相应的事件实现不同的数据流 bbar: new Ext.PagingToolbar({ pageSize: 40,//页面grid显示的数据的条数 store: this._projectStore, displayInfo: true, displayMsg: '当前是第{0}条-第{1}条,共{2}条', emptyMsg: "没有可以显示的记录" })//定义bottomBar,控制分页等的显示,其中0表示第一条数据,1表示当前显示的最后一条数据,2表示数据的总数,会自动向后台发送名称分别为'start,limit'的
参数;可在前端进行分页也可以在服务器端进行,只不过加载数据的速度不同。在前端分页时,是一次性从后台读取数据,而从后台分条读取数据时每次读取一部分数据,比较快捷。 }); this._projectStore.load();//数据集的加载,load的时候客户端向服务器端发送数据请求获得数据; this.on('celldblclick', onCellDblClick);//定义行双击事件,事件触发后用名为onCellDblClick的函数来实现。 } Ext.extend(Ipms.projects.ProjectGridPanel, Ext.grid.GridPanel);
其中定义columnModel
Ipms.projects.ProjectGridPanel_ColumnModel = function () { Ipms.projects.ProjectGridPanel_ColumnModel.superclass.constructor.call(this, [{//这里显示的是当selectionModel是RowSelectionModel的时候,
而当grid的sm为CheckboxSelectionModel ,'{'前边要加上selectModel,在function后边还需要将该变量传进来;
而需要表格内每一行默认按照1234…顺序排序时,这里应加上new Ext.grid.RowNumberer(), header: "id",//列表的标头显示的字样 hidden: true,//设置默认为隐藏,默认为false hideable: false }, { header: "项目名称", dataIndex: 'projectName', sortable: true//设置默认可排序,默认为false } , { header: "状态", dataIndex: 'projectState', renderer:Ipms.projects.projectStateRender,//renderer是将数据显示的时候进行转换,Extjs内部自带的有Date等类型,只需要加上Date.render,
就可以了。 hidden: false, sortable: true }]); this.defaultSortable = false; }; Ext.extend(Ipms.projects.ProjectGridPanel_ColumnModel, Ext.grid.ColumnModel);
本文中,我只是列举了平时用到的一些关于Grid的属性及方法,有一个博客,写的比较详细。特列出来如下,用的时候来查就可以了:
http://hi.baidu.com/tyyczzg/item/33f3c3577b2b1b3f32e0a9d9
定义filters如下
Ipms.expertApplys.ExpertApplyGridPanel_GridFilters = function () { Ipms.expertApplys.ExpertApplyGridPanel_GridFilters.superclass.constructor.call(this, { filters: [ { type: 'string', dataIndex: 'projectName'//GridFilters作用在每一列上,所以dataIndex必须与相应的列的dataIndex一样才会显示相应的筛选框。 }, { type: 'string', dataIndex: 'collegeName' }, { type: 'numeric',//type为numeric时,会显示如下类型的筛选框,前台会自动向后台发送名为'numeric'类型的数据,之后getRange, 在后台获取的时候分别获取'Start'、‘End’,就可以按照范围检索相应的数据了。 dataIndex: 'amounts' }, { type: 'date',//date类型的筛选框如下类型
另外有一种是list类型的如最后一个图片,此时只需要定义一个FilterItems就可以了,如
Ipms.projects.projectStateFilterItems = [{
id: 'ManagerUnSubmit',
text: '负责人未提交'
}] 往后台发送的是id显示的是text,形式上跟comboBox差不多 dataIndex: 'expertApplyTime' }] }) }; Ext.extend(Ipms.expertApplys.ExpertApplyGridPanel_GridFilters, Ext.grid.GridFilters);
Filters相当于Grid的插件,是查询数据的时候更加简便。
2、分组GroupingGridPanel
GroupingGridPanel和普通的GridPanel不同之处在于其Store和显示的GridView定义的Store为
var store = new Ext.data.GroupingStore({ reader: new Ipms.expertApplys.DeviceApplyXmlReader(), url: Ipms.service.expertApplys.ExpertApplyItmService + '/ManagerGetItemsByProject', baseParams: { projectID: project.get('id')//发送到后台的参数 }, sortInfo: { field: 'id', direction: "ASC" },//默认按照id列的升序进行排序 groupField: 'expertName'//按某列进行分组,标题在GridView中显示 }); store.load({params:{start:0,limit:25}});//开始load的时候由于设置的pageSize不太管用于是在第一次加载的时候手动设置开始和需要加载的数目。
而其GridView的定义如下
this._view = new Ext.grid.GroupingView({ forceFit: true,//强制自动填充表格 scrollOffset: 0, groupByText: '按此列进行分组',//将分组字样设置为中文,如果不设置默认英文 enableNoGroups: true,//是否不允许手动分组 showGroupsText: '启用分组',//设置启用分组字样 emptyText: '没有满足条件的项目', groupTextTpl: '<span style="font-size:12px">{text} ({[values.rs.length]} {[ "个申购"]})</span>'//分组grid中显示的分组字样 });
3、带有checkbox的
带有checkBox的grid和普通的grid用法差不多,只不过跟GroupingGrid需要设置View或者Store差不多,这里只需要设置下SelectionModel和ColumnModel,而且只需要将Ext.grid.RowSelectionModel()设置为Ext.grid.CheckboxSelectionModel()在ColumnModel里边加上selectionModel变量就可以了。
在选择的时候Extjs的grid和EXEL的选择事件很像,按住'shift'可以跨列同时选择多行,而按住'Ctrl'可以间隔选择多行。
实际在做的时候checkBoxGrid和GroupingGrid是可以结合起来的如下图,同时设置Store、GridView、SelectionModel和ColumnModel,并且在显示的字段上加了扩展。
this._view = new Ext.grid.GroupingView({ forceFit: true, scrollOffset: 0, startCollapsed: true, enableGroupingMenu: false,//不显示手动分组列表,即每个列的标头点击小蓝色的按钮后出现的自动分组提示 hideGroupedColumn: true, emptyText: '没有满足条件的项目', groupTextTpl: '<span style="font-size:12px"><input class="grpCheckbox" style="vertical-align:middle;" type="checkbox"/>
{text} 万元, ({[values.rs.length]} {[ "个建设计划条目"]})</span>'//此行设置就可以在每个分组头上加一个CheckBox,当check的时候,
自动显示出下面的条目并且加以勾选,如果添加相应的勾选事件,就可以实现如同邮箱里勾选头中的checkbox选中所有条目的情况。
示例代码如下: 在分组的header中添加checkbox,实现整组条目的选中
Ext.override(Ext.grid.GroupingView, {
interceptMouse: function (e) {
var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
if (hd) {
var t = e.getTarget('.grpCheckbox');
if (t) {
var checked = t.checked;
var groupField = this.getGroupField(); // 得到groupField
var idPrefix = this.grid.getGridEl().id + '-gp-' + groupField + '-';
var groupValue = hd.id.substring(idPrefix.length);
var groupValue = groupValue.substring(0, groupValue.lastIndexOf('-')); // 得到groupValue
var grid = this.grid;
grid.getStore().each(function (rec, index) {
var recordValue = rec.get(groupField);
if (recordValue == groupValue) {
if (checked) {
grid.getSelectionModel().deselectRow(index);
} else {
grid.getSelectionModel().selectRow(index, true);
}
}
});
} else {
e.stopEvent();
this.toggleGroup(hd.parentNode);
}
}
}
});
});
另外将组打开或者合起,都有一句非常简单的代码:view.collapseAllGroups();或者view.expandAllGroups();即图中点击收缩和展开的handler事件。
4、editorGridPanel
editorGridPanel与其他Grid不同的地方主要在于它的ColumnModel,在定义一个Panel的时候需要继承自Ext.grid.EditorGridPanel,并且在对应的ColumnModel里边加上editor,其他的定义方式和普通的GridPanel一样。
Ext.extend(Ipms.expertApplys.ExpertApplyExitPanel_DeviceEditGridPanel, Ext.grid.EditorGridPanel);//继承自EditorGridPanel clicksToEdit: 1,//当定义具体的表格时,设置单击事件的条件,这是点击一下就可以对editor进行编辑 autoHeight: true,//设置表格的高度,同以前所说的,在Grid里面设置高度为auto的话比较方便的显示不同的数据和bbar的距离,使页面不会显示一大片空白区域,
看起来比较美观。 //在ColumnModel的某一列内部定义 { header: "申报数量", dataIndex: 'count', hidden: false, width: 80, renderer: function (value, metadata, record) { metadata.attr = 'ext:qtitle="' + '申报数量' + '"' + ' ext:qtip="' + value + '"'; return value; }, editor: isShow ? null : new Ext.form.NumberField({ allowBlank: false, allowNegative: false, allowDecimals:false }) },
在editor 内部也可以加监听事件,而且作为editor的不仅只可以是textField,还可以是comboBox,甚至自定义的控件。
editor: isShow ? null : new Ext.form.ComboBox({//选用ComboBox作为editor store: Ipms.expertApplys.MarketDeviceSourceStore, displayField: 'value', valueField: 'value', triggerAction: 'all', editable: false, allowBlank: false, listeners: { select: function (combox) { var source = combox.getValue(); var selectedItem = selection.getSelected();//加select事件,当选择不同的条目的时候触发,设置当前选中行的其他字段相应的值。 if (source == '供应商') selectedItem.set('webURL', ""); } } })
在使用这种Grid的时候,发现它的验证事件使用的比较多,而且比较有意思:
首先要像定义celldblclick一样定义一个验证函数,但是它的名字叫做validateedit,然后继续定义这个valid事件就可以了,需要注意的是,在使用具体的列时,需要知道当前列在所有列中是从前向后数第几个,然后再get相应的editor内部的东西。
this._store.load(); this.on('celldblclick', onCellDblClick); this.on('validateedit', this.validateedit);
定义validateedit
this.validateedit = function (obj) {//obj是默认传递进去的参数,表示当前的editor var grid = obj.grid;//获得所在的表格 var row = obj.row;//获得当前行号 var column = obj.column;//获得当前的列号 var editor = grid.getColumnModel().getCellEditor(column, row);//获得具体某一个editor var record = obj.record;//获得当前行,是json格式的数据 if (column == 4) { var count = editor.getValue(); var price = record.get('price'); var cost = count * price; record.set('cost', cost); } return true; }//这个函数需要定义在this.on()的前面,因为js加载代码是有顺序的。
Store
用Ajax获取store
Ext.Ajax.request({ url: Ipms.service.devices.DeviceService + '/GetDeviceById', //url: Ipms.service.devices.DeviceService + '/Query', params: { DeviceID: deviceId }, scope: this, success: function (response) { var store = new Ext.data.Store({//用datastore读取 data: response.responseXML,//解析的返回格式为xml reader: new Ipms.expertApplys.DeviceXmlReader()//读取 }); var currentDevice = store.getAt(0); panel = new Ipms.expertApplys.DeviceAffirmPanel(panelId, "查看设备-" + currentDevice.get('deviceName'),
'icon-device-new', currentDevice, purchasePlanItemId, purchasePlanItemStore, isAffirm, false); Ipms.WorkSpace.addPanel(panel); } });
另外一种形式:
var projectStore = new Ipms.projects.ProjectStore(Ipms.service.projects.ProjectService + '/QueryCollegeProject'); var panel = Ipms.WorkSpace.active(panelId); if (!panel) { panel = new Ipms.projects.ProjectGridPanel(panelId, projectStore, name, 'icon-project-list'); Ipms.WorkSpace.addPanel(panel); }//之后再在gridpanel内部进行load()
在Extjs中Store大体分jsonStore、simpleStore、xmlStore等几种,平时从网上浏览的饿时候看到了很多关于store的好用的代码,对store的操作重要的是对行的整体操作或者对某一个record的赋值和取值操作,尤其在grid中,知道了store的这些用法对写代码的效率可以说是大大提高了。所以靠着平时积累也保留了很多:
Store.getCount()返回的是store中的所有数据记录,然后使用for循环遍历整个store,从而得到每条记录。
store.getById(1001).get('name'),按照record 的id获取内部的字段。
store.insert(0,record) 如果希望自己指定数据插入的索引位置,可以使用insert()函数。它的第一个参数表示插入数据的索引位置,可以使用record实例或record实例的数组作为参数,插入之后,后面的数据自动后移。
store.remove(store.getAt(0)) 删除操作可以使用remove()和removeAll()函数,它们分别可以删除指定的record和清空整个store中的数据。
store.getAt(0).set('name', 'xxxx') store中没有专门提供修改某一行record的操作,我们需要先从store中获取一个record。对这个record内部数据的修改会直接反映到store上,在grid中也有grid.getStore()获得grid的store方法。
以上这些都是本人平时用得较多的,其中有一个博客写的很详细,特引进如下,方便以后查阅:
http://www.cnblogs.com/zhangqifeng/archive/2009/05/25/1489162.html