君子王焕

博客园 首页 新随笔 联系 订阅 管理

在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"/>
&nbsp;&nbsp;{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

 

posted on 2013-05-21 13:39  君子王焕  阅读(2795)  评论(1编辑  收藏  举报