首先,一個表格應該有列定義,即定義表頭ColumnModel:
// 定義一個ColumnModel,表頭中有四列
var cm = new Ext.grid.ColumnModel([
{header:'編號',dataIndex:'id'},
{header:'性別',dataIndex:'sex'},
{header:'名稱',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
cm.defaultSortable = true;
該ColumnModel定義了表格的四個列,其每列的名稱和對應的數據鍵。請注意defaultSortable屬性,即為每個列都安上一個可以排序的功能。如果只想某些列舉有該功能,可以設置:
{header:'編號',dataIndex:'id',Sortable:true},
現在就來看看這個Ext.data.Store是如何轉換三種數據的。
1.二維數組:
// ArrayData
var data = [
['1','male','name1','descn1'],
['2','male','name1','descn2'],
['3','male','name3','descn3'],
['4','male','name4','descn4'],
['5','male','name5','descn5']
];
// ArrayReader
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id',mapping: 0},
{name: 'sex',mapping: 1},
{name: 'name',mapping: 2},
{name: 'descn',mapping: 3}
])
});
ds.load();
ds要對應兩個部分:proxy和reader。proxy告訴我們從哪里獲得數據,reader告訴我們如何解析這個數據。
現在用的是Ext.data.MemoryProxy,它將內存中的數據data作為參數傳遞。Ext.data.ArrayReader專門用來解析數組,并且告訴我們它會按照定義的規范進行解析,每行按順序讀取四個數據,第一個叫id,第二個叫sex,第三個叫name,第四個descn。這些是跟cm定義中的dataIndex對應的。這樣cm就知道哪列應該顯示那條數據了。
mapping屬性用于標記data中的讀取后的數據與標頭的映射關系,一般是不用設置的。但如果我們想讓sex的數據中name欄中出現,可以設置mapping值。即id的mapping為2,后者為0。
記得要執行一次ds.load(),對數據進行初始化。
數據的顯示顯得非常簡單:
HTML文件:
<div id='grid'></div>
JS文件:
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm
});
grid.render();
其顯示結果為:
2.如何在表格中添加CheckBox呢?
var sm = new Ext.grid.CheckboxSelectionModel();
var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),//自動行號
sm,//添加的地方
{header:'編號',dataIndex:'id'},
{header:'性別',dataIndex:'sex'},
{header:'名稱',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,//添加的地方
title: 'HelloWorld'
});
3. 如何做Grid上觸發事件呢?
下面是一個cellclick事件
grid.addListener('cellclick', cellclick);
function cellclick(grid, rowIndex, columnIndex, e) {
var record = grid.getStore().getAt(rowIndex); //Get the Record
var fieldName = grid.getColumnModel().getDataIndex(columnIndex); //Get field name
var data = record.get(fieldName);
Ext.MessageBox.alert('show','當前選中的數據是'+data);
}
4.如何做Grid中做出快捷菜單效果:
grid.addListener('rowcontextmenu', rightClickFn);//右鍵菜單代碼關鍵部分
var rightClick = new Ext.menu.Menu({
id:'rightClickCont', //在HTML文件中必須有個rightClickCont的DIV元素
items: [
{
id: 'rMenu1',
handler: rMenu1Fn,//點擊后觸發的事件
text: '右鍵菜單1'
},
{
//id: 'rMenu2',
//handler: rMenu2Fn,
text: '右鍵菜單2'
}
]
});
function rightClickFn(grid,rowindex,e){
e.preventDefault();
rightClick.showAt(e.getXY());
}
function rMenu1Fn(){
Ext.MessageBox.alert('right','rightClick');
}
其Grid如下:
5.如何將一列中的數據根據要求進行改變呢?
比如說性別字段根據其male或female改變顯示的顏色,這種ColumnMode中設計:
var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
sm,
{header:'編號',dataIndex:'id'},
{header:'性別',dataIndex:'sex',renderer:changeSex},
{header:'名稱',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
cm.defaultSortable = true;
function changeSex(value){
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>紅男</span>";
} else {
return "<span style='color:green;font-weight:bold;'>綠女</span>";
}
}
其它兩種數據的Grid顯示是相同的,其不同之處在于數據獲取的過程:
6.Json數據
至于這種數據的類型請大家自己看Ajax的書籍:
//JsonData
var data = {
'coders': [
{ 'id': '1', 'sex': 'male', 'name':'McLaughlin', 'descn': 'brett@newInstance.com' },
{ 'id': '2', 'sex': 'male','name':'Hunter', 'descn': 'jason@servlets.com' },
{ 'id': '3', 'sex': 'female','name':'Harold', 'descn': 'elharo@macfaq.com' },
{ 'id': '4', 'sex': 'male','name':'Harolds', 'descn': 'elhaross@macfaq.com' }
],
'musicians': [
{ 'id': '1', 'name': 'Clapton', 'descn': 'guitar' },
{ 'id': '2', 'name': 'Rachmaninoff', 'descn': 'piano' }
]
}
//ds使用的MemoryProxy對象和JsonReader對象
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.JsonReader({root: 'coders'}, [
{name: 'id'},
{name: 'sex'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load();
var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,
title: 'HelloWorld',
autoHeight: true//一定要寫,否則顯示的數據會少一行
});
grid.render();
7.使用XML數據:
注意,讀取XML數據必須在服務器上進行。
XML數據test.xml的內容:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<results>2</results>
<item>
<id>1</id>
<sex>male</sex>
<name>Taylor</name>
<descn>Coder</descn>
</item>
</dataset>var ds3 = new Ext.data.Store({
url: 'test.xml', //XML數據
reader: new Ext.data.XmlReader({record: 'item'}, [ //使用XmlReader對象
{name: 'id'},
{name: 'sex'},
{name: 'name'},
{name: 'descn'}
])
});
8.從服務器獲取數據和數據翻頁控件
從一個服務器文件,如ASP、JSP或Servlet中獲得數據二維Array、JSON或XML數據,也可以被Ext讀取,并被Grid顯示:
服務器文件data.asp:
<%
start = cint(request("start"))
limit = cint(request("limit"))
dim json
json=cstr("{totalProperty:100,root:[")
for i = start to limit + start-1
json =json + cstr("{'id':'") +cstr(i) + cstr("','name':'name") + cstr(i) + cstr("','descn':'descn") + cstr(i) + cstr("'}")
if i <> limit + start - 1 then
json =json + ","
end if
next
json = json +"]}"
response.write(json)
%>
我們可以看到,這個頁面會根據傳入的start和limit的不同,返回不同的數據,其實質是個分頁的代碼。下面是start=0,limit=10的JSON數據:
{totalProperty:100,root:[{'id':'0','name':'name0','descn':'descn0'},{'id':'1','name':'name1','descn':'descn1'},{'id':'2','name':'name2','descn':'descn2'},{'id':'3','name':'name3','descn':'descn3'},{'id':'4','name':'name4','descn':'descn4'},{'id':'5','name':'name5','descn':'descn5'},{'id':'6','name':'name6','descn':'descn6'},{'id':'7','name':'name7','descn':'descn7'},{'id':'8','name':'name8','descn':'descn8'},{'id':'9','name':'name9','descn':'descn9'}]}
我們使用分頁控件來控制Grid的數據:
Ext.onReady(function(){
var sm = new Ext.grid.CheckboxSelectionModel();
var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
sm,
{header:'編號',dataIndex:'id'},
{header:'性別',dataIndex:'sex'},
{header:'名稱',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
cm.defaultSortable = true;
var ds = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url:'data.asp'}),
reader: new Ext.data.JsonReader({
totalProperty: 'totalProperty',
root: 'root'
}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load({params:{start:0,limit:10}});
var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,
title: 'ASP->JSON',
bbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
emptyMsg: "沒有記錄"
}),
tbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '顯示第 {0} 條到 {1} 條記錄,一共 {2} 條',
emptyMsg: "沒有記錄"
})
});
grid.render();
})
10.如何在Grid的上方添加按鈕呢?
添加按鈕的關鍵之處在于tbar或bbar屬性設置Toolbar工具條:
var grid = new Ext.grid.GridPanel({
el: 'grid3',
ds: ds,
cm: cm,
sm: sm,
title: 'HelloWorld',
tbar: new Ext.Toolbar({
items:[
{
id:'buttonA'
,text:"Button A"
,handler: function(){ alert("You clicked Button A"); }
}
,
new Ext.Toolbar.SplitButton({})
,{
id:'buttonB'
,text:"Button B"
,handler: function(){ alert("You clicked Button B"); }
}
,
'-'
,{
id:'buttonc'
,text:"Button c"
}
]
})
});
11.將GridPanel放入一個Panel或TabPanel中
var tabs = new Ext.TabPanel({
collapsible: true
,renderTo: 'product-exceptions'
,width: 450
,height:400
,activeTab: 0
,items:[
{
title: 'Unmatched'
},{
title: 'Matched'
}
]
});
tabs.doLayout();
var panel = new Ext.Panel({
renderTo: 'panel',
title:'panel',
collapsible:true,
width:450,
height:400,
items:[grid] //管理grid
});
Panel必須有DIV存在。其包含的Component有items管理。
在實際的網頁開發中,大部分時間都要涉及到Form表單的處理。在Ext框架中也提供了很多這方面的控件,而且還有一個專門的FormPanel布 局,該布局默認為放在面板上面的所有控件都是換行放置,而在實際應用中為了美觀,有些需要橫排,特別是Radio控件,這個時候就需要我們重新定制這些控 件的布局了,該例子中使用CSS來實現這些功能,先貼出一張效果圖。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Ext中FormPanel面板及Form控件橫排測試(CSS)</title>
<link rel="stylesheet" type="text/css" media="all" href="../ext/resources/css/ext-all.css" />
<style type="text/css" media="all">
.allow-float {clear:none!important;} /* 允許該元素浮動 */
.stop-float {clear:both!important;} /* 阻止該元素浮動 */
.sex-male {float:left;}
.sex-female {float:left;padding:0 0 0 20px;}
.age-field {float:left;padding:0 0 0 58px;*padding:0 0 0 50px!important;*padding:0 0 0 50px;}
</style>
</head>
<body>
<script type="text/javascript" src="../ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext/ext-all.js"></script>
<script type="text/javascript" src="../ext/build/locale/ext-lang-zh_CN.js"></script>
<script type="text/javascript">Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';</script>
<script type="text/javascript">
Ext.onReady(function() {
//創建Form面板
var fp = new Ext.form.FormPanel({
buttonAlign:'center',
labelAlign:'right',
labelWidth:40,
frame:true,
bodyStyle:'padding:8px 0 0 0;',
items:[{
xtype:'textfield',
fieldLabel:'姓名',
name:'n_username',
id:'i_username',
width:320
},{
xtype:'radio',
fieldLabel:'性別',
boxLabel:'男',
name:'sex',
id:'male',
itemCls:'sex-male', //向左邊浮動,處理控件橫排
clearCls:'allow-float', //允許兩邊浮動,在實際生成的HTML結構中有專門的DIV阻斷浮動
checked:true
},{
xtype:'radio',
boxLabel:'女',
name:'sex',
id:'female',
itemCls:'sex-female', //向左浮動,處理控件橫排
clearCls:'allow-float', //允許兩邊浮動
hideLabel:true //不顯示前面"性別"的標簽
},{
xtype:'textfield',
fieldLabel:'年齡',
name:'n_age',
id:'i_age',
itemCls:'age-field', //向左浮動,處理控件橫排
width:133
},{
xtype:'textfield',
fieldLabel:'住址',
name:'n_address',
id:'i_address',
itemCls:'stop-float', //不允許浮動,結束控件橫排
width:320
}],
buttons:[{
text:'確定',
handler:onOK //實際應用一般是處理fp.getForm.submit()事件
}, {
text:'重置',
handler:function(){ fp.getForm().reset(); }
}],
keys:[{ //處理鍵盤回車事件
key:Ext.EventObject.ENTER,
fn:onOK,
scope:this
}]
});
//確定按鈕事件,這里只是簡單獲取各控件值,實際應用一般和后臺腳本結合
function onOK() {
var strMsg;
strMsg = ‘姓名:’ + fp.getComponent(’i_username’).getValue() + ‘,性別:’;
if (fp.getComponent(’male’).checked) strMsg += ‘男’;
if (fp.getComponent(’female’).checked) strMsg += ‘女’;
strMsg += ‘,年齡:’ + fp.getComponent(’i_age’).getValue();
strMsg += ‘,住址:’ + fp.getComponent(’i_address’).getValue();
alert(strMsg);
}
//創建主窗口
new Ext.Window({
title:’Ext中FormPanel面板及Form控件橫排測試(CSS)’,
width:400,
closable:false,
collapsible:true,
draggable:false,
resizable:false,
modal:true,
border:false,
items:[fp],
buttons:[]
}).show();
});
</script>
</body>
</html>
二、使用
安裝完后你去試,發現沒有用,其實還有一些操作如下:
1、執行這個操作:Window → Preferences → Spket → JavaScript Profiles → New
2、在彈出框中輸入ExtJs,然后點OK。
3、然后選擇ExtJs點Add Library,把你下載的ext包中找到/source/ext.jsb加載進來
4、然后先中ExtJs點擊右邊的default按鈕.
5、然后點擊確定就搞定。你現在有eclipse中建立一個JS用Ext.就會出現提示咯!!!
演示(demo)地址在文章最后.
效果圖如下:
源代碼包括 0005_checkbox_reorder.html,0005_checkbox_reorder_tree.php.
0005_checkbox_reorder.html
Ext2.X提供了簡單的checkbox實現,但對于一些復雜的需求,如: 級聯多選(選中父結點,自選中其所有子結點和所有父結點) , 單選等等, Ext2.X并沒有幫我們實現
還有最難解決的情況, 當樹是異步的時候, 要想級聯多選, 實現起來有些難度
在此, 通過對Ext.tree.TreeNodeUI進行擴展,這些問題都得到很好的解決
el決定了樹的顯示位置,一般是個div例如
dataUrl決定了樹的json數據來源,我這里是一個struts的action,這個action會輸出json數據
在服務層要提供一個可以生成json格式數據的service,struts的任務是獲取傳來的參數調用service方法輸出json
我在服務層生成json數據用的是jsonlib包,論壇有詳細介紹的帖子,就不多說了
數據庫有兩個表來構建樹,一個是樹的節點表,至少包括樹的id name 我這里還有一個haschild,代表有沒有子節點。
另一個是節點關系表,兩列分別是父節點和他對應的子節點。
service層調用dao的方法將結果集組裝成List或者Map,再用jsonlib包提供的api將list轉化成json,例如
在action里面調用這個service方法:
這樣一個完整的樹就生成了,現在這個樹是只有兩層,如果是多層的就需要修改service方法來遞歸構造一個樹的list再轉化成json。
異步讀取節點:首先,底層的service方法要做到每次生成的是傳入參數的下一級節點的list,然后在js的 tree.setRootNode(root);下面加上這句:js 代碼
tree.loader.dataUrl 的值需要返回的就是該節點id的下一級的json數據
數據量大的時候異步加載要好的多,服務層也代碼比起一次性全部加載的反復遞歸調用省不少。