Extjs4——实现动态的grid(即实现数据库表数据的显示)

  毕设大部分功能已经完成,目前还在完善一些辅助功能,其中数据库管理就是一个重点,这一主要介绍通过Ext显示数据库的表。

一、服务器端的实现

  由于之前已经有过实现的经验,因此服务器端的实现已经轻车熟路,下边先介绍这一块。

  其实从面向对象的角度来说,特别是采用了SSH框架之后,我们可以直接通过hibernate获取对应表对象的集合,然后将集合发送至前台交给Ext处理。这样看起来挺不错,而且实际实现也不难,但是你仔细查看就会发现个很不爽的事情,每次发送的集合包含了大量的无用数据(甚至绝大多数的数据),为什么会这样呢?表关联的原因。hibernate生成的model会引入关联表的对象(或对象集合),而struts—json插件会将他们全部序列化,这在我们实际Ext的显示中不需要的。当然,你或许可以无视,但这绝对是个糟糕的设计,你将大量的网络流量耗费在了无效数据上。

  那么怎么解决这个问题呢?有两个方法:一是通过struts—json提供的方法(一般用注解或result配置)指定这些数据不序列化,听着挺好,但做着费劲,你要么在model类中写入很多和这个类本身没有任何关系的注解,要么需要就在action的<result>标签内对每一个字段进行指定,这个听听都头疼;另外一种方法或许靠谱些,可以对每个model对应一个简化的model,在hibernate读取集合后将集合转化为该类型的,事实上我在处理多表关联数据显示时就用的这个方法,但是你觉得对于每个实体定义两个model合适吗?

  既然这两种都不行,那么怎么处理呢?其实完全可以抛开hibernate,采用原始点的方法:先sql读取所有表名,然后根据表名读出字段名和对应数据,其中表数据使用二维数据存数即可,事实证明这种方法更灵活。

  下边是实现代码:

View Code
  1     /**

  2      * 获取表名

  3      * @return    List<表明>

  4      */

  5     public List<MyDataBase> getTables(){

  6         List<MyDataBase> mdbls=new ArrayList<MyDataBase>();

  7         Session se=HibernateSessionFactory.getSession();

  8         SQLQuery sq=se.createSQLQuery("show tables");

  9         List<String> sls=sq.list();

 10         for(String str:sls){

 11             if("jbpm".equals(str.substring(0, 4)))

 12                 continue;

 13             MyDataBase mdb=new MyDataBase();

 14             mdb.setTablename(str);

 15             mdbls.add(mdb);

 16         }

 17         return mdbls;

 18     }

 19     

 20     /**

 21      * 获取字段名    

 22      * @param tablename    表名

 23      * @return

 24      */

 25     public List<MyDataBase> getFields(String tablename){

 26         List<MyDataBase> mdbls=new ArrayList<MyDataBase>();

 27         Session se=HibernateSessionFactory.getSession();

 28         SQLQuery sq=se.createSQLQuery("desc "+tablename).addScalar("Field");

 29         List<String> sls=sq.list();

 30         for(String str:sls){

 31             MyDataBase mdb=new MyDataBase();

 32             mdb.setFieldname(str);

 33             mdbls.add(mdb);

 34         }

 35         return mdbls;

 36     }

 37     

 38     /**

 39      * 获取字段

 40      * @param tablename 表名

 41      * @return

 42      */

 43     public String[] getFieldsInArray(String tablename){

 44         String[] fields;

 45         Session se=HibernateSessionFactory.getSession();

 46         SQLQuery sq=se.createSQLQuery("desc "+tablename).addScalar("Field");

 47         List<String> sls=sq.list();

 48         fields=new String[sls.size()];

 49         for(int i=0;i<sls.size();i++){

 50             fields[i]=sls.get(i);

 51         }

 52         return fields;

 53     }

 54     

 55     /**

 56      * 获取表内容

 57      * @param tablename

 58      * @return

 59      */

 60     public String[][] getTableContent(String tablename){

 61         String[][] content=null;

 62         Session se=HibernateSessionFactory.getSession();

 63         SQLQuery sq=se.createSQLQuery("select * from "+tablename);

 64         List<Object[]> ls=sq.list();

 65         content=new String[ls.size()][getFields(tablename).size()];

 66         for(int i=0;i<ls.size();i++){

 67             Object[] strs=ls.get(i);

 68             for(int j=0;j<strs.length;j++){

 69                 content[i][j]=strs[j]==null?"":strs[j].toString();

 70             }

 71         }

 72         return content;

 73     }

 74     

 75     /**

 76      * 将字段名集合处理为JSON格式的字符串

 77      * @param tablename    对应表名

 78      * @return    字符串数组,每一项为一个Ext中grid的一个header

 79      */

 80     public String[] getfiledsHeaders(String tablename){

 81         String[] fields=this.getFieldsInArray(tablename);

 82         String[] content=new String[fields.length];

 83         String temp="{text:'#1',dataIndex:'#1',flex:1}";

 84         

 85         for(int i=0;i<fields.length;i++){

 86             content[i]=temp.replace("#1", fields[i]);

 87         }

 88         return content;

 89     }

 90     

 91     /**

 92      * 将数据处理为JSON格式的字符串

 93      * @param tablename    对应表名

 94      * @return    字符串数组,每一项为一条数据库记录

 95      */

 96     public String[] getContentStr(String tablename){

 97         String[] fields=this.getFieldsInArray(tablename);

 98         String[][] content=this.getTableContent(tablename);

 99         String jsonContent[]=new String[content.length];

100         for(int i=0;i<content.length;i++){

101             String temp="";

102             for(int j=0;j<fields.length;j++){

103                 temp=temp+"'"+fields[j]+"':'"+content[i][j]+"',";

104             }

105             temp="{"+temp.substring(0, temp.length()-1)+"}";

106             jsonContent[i]=temp;

107         }

108     

109         return jsonContent;

110     }

  其中最终发送客户端的字段头格式如下:

"fieldheader":["{text:'rid',dataIndex:'rid',flex:1}","{text:'rname',dataIndex:'rname',flex:1}","{text:'rstring',dataIndex:'rstring',flex:1}"],"fields":["rid","rname","rstring"]

  表数据格式如下:

"contentstr":["{'rid':'1','rname':'系统管理员','rstring':'admin'}","{'rid':'2','rname':'实训负责人','rstring':'manager'}","{'rid':'3','rname':'指导老师','rstring':'teacher'}","{'rid':'4','rname':'组长','rstring':'header'}","{'rid':'5','rname':'学生','rstring':'student'}"]

二、Extjs中grid的实现

  其实实现动态grid的思路很简单,我们知道grid的表头是由columns属性指定的,而加载的数据是由对应的store决定的,想要让其动态改变,只需修改columns和store即可,而恰好Ext提供了reconfigure(Ext.data.Store store, Object[] columns)方法来实现这一操作。

  Extjs里边首先需要一个combox下拉框,在打开grid的时候加载表名以供选择,其实现如下:

{

                 xtype: 'combobox',

                 width: 219,

                 id:'combtables',

                 fieldLabel: '选择表',

                 labelWidth: 50,

                 maxWidth: 200,

                 editable:false,

                 valueField: 'tablename',

                 displayField: 'tablename',

                 store:Ext.create('sxpt.store.admin.Tables'),      //对应store请求获取表名

                 labelWidth: 80

}

  为实现动态的grid,我们首先要实现一个未指定store和空columns的grid,其实现代码如下:

View Code
 1 Ext.define('sxpt.view.admin.DataBaseList',{

 2     extend: 'Ext.grid.Panel',

 3     alias: 'widget.databaselist',

 4     id:'databaselist',

 5     title: '数据库管理',  

 6     region: 'center', 

 7     renderTo:Ext.getBody(),

 8     columns:[],

 9     bbar: {  

10         xtype: 'pagingtoolbar',

11         id:'datapagebar',

12         displayInfo: true,

13         displayMsg: '显示 {0} - {1} 共 {2}条',  

14         emptyMsg: "没有数据需要显示"  

15     }, 

16       dockedItems:[{

17           dock: 'top',

18           xtype: 'toolbar',

19           layout:'fit',

20           items: [

21               {

22                   xtype:'tabpanel',

23                   height:80,

24                   items:[{

25                       xtype:'panel',

26                       title:'查询表',

27                       margin: '5 0 0 20',

28                       items:[

29                       {

30                              xtype: 'combobox',

31                             width: 219,

32                             id:'combtables',

33                             fieldLabel: '选择表',

34                             labelWidth: 50,

35                             maxWidth: 200,

36                             editable:false,

37                             valueField: 'tablename',

38                             displayField: 'tablename',

39                             store:Ext.create('sxpt.store.admin.Tables'),

40                             labelWidth: 80,

41  

42                       }

43                       ]

44                   }

45           ]

46       }]

47 });

  之后为了每次选择表后就加载数据,在combobox中添加change监听器,实现如下:

 1                            listeners:{

 2                                 change:function(combo, record,index){

 3                                     var griddb=Ext.getCmp('databaselist');

 4                                     Ext.Ajax.request({

 5                                         url:'admin/admin_database_fieldsa',

 6                                         params:{

 7                                             tablename:this.value

 8                                         },

 9                                         method : 'POST',

10                                         success : function(response) {

11                                             var strT=response.responseText;

12                                             

13                                             var json = Ext.JSON.decode(strT.replace(/\"\{/g,"{").replace(/\}\"/g,"}"));                //替换掉由                                                                 于struts-json序列化产生的多余双引号

14                                             var store=Ext.create('Ext.data.Store',{

15                                                 fields:json.fields,

16                                                 data:json.contentstr

17                                             });

18                                             var pagebar=Ext.getCmp('datapagebar');

19                                             pagebar.bind(store);            //为分页栏加载数据 20                                             store.load();

21                                             griddb.reconfigure(store,json.fieldheader);

22                                         }

  至此,动态的grid就已经完成了。

三、一个问题

  如果你注意struts—json插件的处理结果的话就会发现,它对String类型的属性序列化是会自动加上引号,如上边字段头格式序列化后为:

"fieldheader":["{text:'rid',dataIndex:'rid',flex:1}","{text:'rname',dataIndex:'rname',flex:1}","{text:'rstring',dataIndex:'rstring',flex:1}"]

  但是我们期望的数据格式应该是不带红色引号的。这两者什么区别呢?主要是字符串执行Ext.JSON.decode()后的结果不一样,带引号的反序列化之后fieldheader是一个包含三个字符串的集合(这与服务器端一致,但却并非我们想要的),而不带引号的反序列化之后fieldheader里边包含的是3个对象,每个对象里边包含三个字段,这样的格式才是Extjs可以正确处理的json数据格式。

  因此需要在反序列化之前对接收的字符串进行如下处理:

strT.replace(/\"\{/g,"{").replace(/\}\"/g,"}")

  一下是完成的js代码:

DataBaseList.js
 1 Ext.define('sxpt.view.admin.DataBaseList',{

 2     extend: 'Ext.grid.Panel',

 3     alias: 'widget.databaselist',

 4     id:'databaselist',

 5     title: '数据库管理',  

 6     region: 'center', 

 7     renderTo:Ext.getBody(),

 8     //store: 'admin.Teacher',

 9     columns:[],

10     bbar: {  

11         xtype: 'pagingtoolbar',

12         id:'datapagebar',

13         displayInfo: true,

14         displayMsg: '显示 {0} - {1} 共 {2}条',  

15         emptyMsg: "没有数据需要显示"  

16     }, 

17       dockedItems:[{

18           dock: 'top',

19           xtype: 'toolbar',

20           layout:'fit',

21           items: [

22               {

23                   xtype:'tabpanel',

24                   height:80,

25                   items:[{

26                       xtype:'panel',

27                       title:'查询表',

28                       margin: '5 0 0 20',

29                       items:[

30                       {

31                              xtype: 'combobox',

32                             width: 219,

33                             id:'combtables',

34                             fieldLabel: '选择表',

35                             labelWidth: 50,

36                             maxWidth: 200,

37                             editable:false,

38                             valueField: 'tablename',

39                             displayField: 'tablename',

40                             store:Ext.create('sxpt.store.admin.Tables'),

41                             labelWidth: 80,

42                             listeners:{

43                                 change:function(combo, record,index){

44                                     var griddb=Ext.getCmp('databaselist');

45                                     Ext.Ajax.request({

46                                         url:'admin/admin_database_fieldsa',

47                                         params:{

48                                             tablename:this.value

49                                         },

50                                         method : 'POST',

51                                         success : function(response) {

52                                             var strT=response.responseText;

53                                             

54                                             var json = Ext.JSON.decode(strT.replace(/\"\{/g,"{").replace(/\}\"/g,"}"));

55                                             var store=Ext.create('Ext.data.Store',{

56                                                 fields:json.fields,

57                                                 data:json.contentstr

58                                             });

59                                             var pagebar=Ext.getCmp('datapagebar');

60                                             pagebar.bind(store);

61                                             store.load();

62                                             griddb.reconfigure(store,json.fieldheader);

63                                         }

64                                     })

65                                 }

66                             }

67                       }

68                       ]

69                   }

70                   }

71           ]

72       }],

73       initComponent: function () {

74           this.callParent(arguments);

75       }

76 });

 

  源码暂时就不共享了,等过一段整理好了再发。

你可能感兴趣的:(extjs4)