zoukankan      html  css  js  c++  java
  • Extjs的GridPanel、ColumnModel、GridView、PagingToolbar及Store

    在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, 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

  • 相关阅读:
    JavaScript实现常用的排序算法
    jQuery学习之路(8)- 表单验证插件-Validation
    jQuery学习之路(7)- 用原生JavaScript实现jQuery的某些简单功能
    jQuery学习之路(6)- 简单的表格应用
    jQuery学习之路(5)- 简单的表单应用
    jQuery学习之路(4)- 动画
    JavaScript常见的五种数组去重的方式
    jQuery学习之路(3)- 事件
    jQuery学习之路(2)-DOM操作
    Docker使用非root用户
  • 原文地址:https://www.cnblogs.com/jzwh/p/3090589.html
Copyright © 2011-2022 走看看