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 });

 

  源碼暫時就不共享了,等過一段整理好了再發。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM