第七章 、使用表格控件
7.1 、基本表格 GridPanel
E xtJS 中的表格功能非常强大,包括了排序、缓存、拖动、隐藏某一列、自动显示行 号 、
列汇总、单元格编辑等实用功能。
表格由类 Ext.grid.GridPanel 定义,继承自 Panel ,其 xtype 为 grid 。 ExtJS 中,表格 Gri d
必须包含列定义信息,并指定表格的数据存储器 Store 。表格的列信息由类
Ext.grid.ColumnModel 定义、而表格的数据存储器由 Ext.data.Store 定义,数据存储器根据 解
析的数据不同分为 JsonStore 、 SimpleStroe 、 GroupingStore 等。
我们首先来看最简单的使用表格的代码:
Ext.onReady(function(){
var data=[ [1, 'EasyJWeb', 'EasyJF','www.easyjf.com'],
[2, 'jfox', 'huihoo','www.huihoo.org'],
[3, 'jdon', 'jdon','www.jdon.com'],
[4, 'springside', 'springside','www.springside.org.cn'] ];
var store=new Ext.data.SimpleStore({data:data,fields:["id","name","organization","homepage"]});
var grid = new Ext.grid.GridPanel({
renderTo:"hello",
title:" 中国 Java 开源产品及团队 ",
height:150,
600,
columns:[{header:" 项目名称 ",dataIndex:"name"},
{header:" 开发团队 ",dataIndex:"organization"},
{header:" 网址 ",dataIndex:"homepage"}],
store:store,
autoExpandColumn:2
});
});
执行上面的代码,可以得到一个简单的表格,如下图所示:
上面的代码中,第一行 “ var data= …” 用来定义表格中要显示的数据,这是一个 [][] 二维 数
组;第二行 “ var store= …” 用来创建一个数据存储,这是 GridPanel 需要使用配置属性,数据
存储器 Store 负责把各种各样的数据(如二维数组、 JSon 对象数组、 xml 文本)等转换成 E xtJS
的数据记录集 Record ,关于数据存储器 Store 我们将在下一章中作专门介绍。第三行 “ var gr id
= new Ext.grid.GridPanel( … ) ” 负责创建一个表格,表格包含的列由 columns 配置属性来 描述 ,
columns 是一数组,每一行数据元素描述表格的一列信息,表格的列信息包含列头显示文 本
(header) 、列对应的记录集字段 (dataIndex) 、列是否可排序 (sorable) 、列的渲染函数 (renderer) 、
宽度 (width) 、格式化信息 (format) 等,在上面的列子中只用到了 header 及 dataIndex 。
下面我们看简单看看表格的排序及隐藏列特性,简单修改一下上面的代码,内容如下:
Ext.onReady(function(){
var data=[ [1, 'EasyJWeb', 'EasyJF','www.easyjf.com'],
[2, 'jfox', 'huihoo','www.huihoo.org'],
[3, 'jdon', 'jdon','www.jdon.com'],
[4, 'springside', 'springside','www.springside.org.cn'] ];
var store=new Ext.data.SimpleStore({data:data,fields:["id","name","organization","homepage"]});
var colM=new Ext.grid.ColumnModel([{header:" 项目名称 ",dataIndex:"name",sortable:true},
{header:" 开发团队 ",dataIndex:"organization",sortable:true},
{header:" 网址 ",dataIndex:"homepage"}]);
var grid = new Ext.grid.GridPanel({
renderTo:"hello",
title:" 中国 Java 开源产品及团队 ",
height:200,
600,
cm:colM,
store:store,
autoExpandColumn:2
});
});
直接使用 new Ext.grid.ColumnModel 来创建表格的列信定义信息,在 “ 项目名称 “ 及 “ 开
发团队 ” 列中我们添加了 sortable 为 true 的属性,表示该列可以排序,执行上面的代码,我
们可以得到一个支持按 “ 项目名称 “ 或 “ 开发团队 ” 的表格,如图 xxx 所示。
( 按项目名称排序 )
( 可排序的列表头后面小按钮可以弹出操作菜单 )
另外,每一列的数据渲染方式还可以自己定义,比如上面的表格中,我们希望用户在 表
格中点击网址则直接打开这些开源团队的网站,也就是需要给网址这一列添加上超级连接。
下面的代码实现这个功能:
function showUrl(value)
{
return " "+value+" ";
}
Ext.onReady(function(){
var data=[ [1, 'EasyJWeb', 'EasyJF','www.easyjf.com'],
[2, 'jfox', 'huihoo','www.huihoo.org'],
[3, 'jdon', 'jdon','www.jdon.com'],
[4, 'springside', 'springside','www.springside.org.cn'] ];
var store=new Ext.data.SimpleStore({data:data,fields:["id","name","organization","homepage"]});
var colM=new Ext.grid.ColumnModel([{header:" 项目名称 ",dataIndex:"name",sortable:true},
{header:" 开发团队 ",dataIndex:"organization",sortable:true},
{header:" 网址 ",dataIndex:"homepage",renderer:showUrl}]);
var grid = new Ext.grid.GridPanel({
renderTo:"hello",
title:" 中国 Java 开源产品及团队 ",
height:200,
600,
cm:colM,
store:store,
autoExpandColumn:2
});
});
上面的代码跟前面的示例差别不大,只是在定义 “ 网址 ” 列的时候多了一个 renderer 属 性 ,
即 {header:" 网址 ",dataIndex:"homepage",renderer:showUrl} 。 showUrl 是一个自定义的函数,
内容就是根据传入的 value 参数返回一个包含 <a> 标签的 html 片段。运行上面的代码显示 结
果如下图所示:
自定义的列渲染函数可以实现在单元格中显示自己所需要的各种信息,只是的浏览器 能
处理的 html 都可以。
除了二级数组以外,表格还能显示其它格式的数据吗?答案是肯定的,下面假如我们 的
表格数据 data 定义成了下面的形式:
var data=[{id:1,
name:'EasyJWeb',
organization:'EasyJF',
homepage:'www.easyjf.com'},
{id:2,
name:'jfox',
organization:'huihoo',
homepage:'www.huihoo.org'},
{id:3,
name:'jdon',
organization:'jdon',
homepage:'www.jdon.com'},
{id:4,
name:'springside',
organization: 'springside',
homepage:'www.springside.org.cn'}
];
也就是说数据变成了一维数组,数组中的每一个元素是一个对象,这些对象包含 name 、
organization 、 homepage 、 id 等属性。要让表格显示上面的数据,其实非常简单,只需要把
store 改成用 Ext.data.JsonStore 即可,代码如下:
var store=new Ext.data.JsonStore({data:data,fields:["id","name","organization","homepage"]});
var colM=new Ext.grid.ColumnModel([{header:" 项目名称 ",dataIndex:"name",sortable:true},
{header:" 开发团队 ",dataIndex:"organization",sortable:true},
{header:" 网址 ",dataIndex:"homepage",renderer:showUrl}]);
var grid = new Ext.grid.GridPanel({
renderTo:"hello",
title:" 中国 Java 开源产品及团队 ",
height:200,
600,
cm:colM,
store:store,
autoExpandColumn:2
});
上面的代码得到的结果与前面的一样。当然,表格同样能显示 xml 格式的数据,假如
上面的数据存放成 hello.xml 文件中,内容如下:
为了把这个 xml 数据用 ExtJS 的表格 Grid 进行显示,我们只需要把 store 部分的内
容调整成如下的内容即可:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<row>
<id>1</id>
<name>EasyJWeb</name>
<organization>EasyJF</organization>
<homepage>www.easyjf.com</homepage>
</row>
<row>
<id>2</id>
<name>jfox</name>
<organization>huihoo</organization>
<homepage>www.huihoo.org</homepage>
</row>
<row>
<id>3</id>
<name>jdon</name>
<organization>jdon</organization>
<homepage>www.jdon.com</homepage>
</row>
<row>
<id>4</id>
<name>springside</name>
<organization>springside</organization>
<homepage>www.springside.org.cn</homepage>
</row>
</dataset>
var store=new Ext.data.Store({
http://www.cnblogs.com/liu2008hz/admin/%22hello.xml",
reader:new Ext.data.XmlReader({
record:"row"},
["id","name","organization","homepage"])
});
其它的部分不用改变,完整的代码如下:
function showUrl(value)
{
return "<a href='http://"+value+"' target='_blank'>"+value+"</a>";
}
Ext.onReady(function(){
var store=new Ext.data.Store({
http://www.cnblogs.com/liu2008hz/admin/%22hello.xml",
reader:new Ext.data.XmlReader({
record:"row"},
["id","name","organization","homepage"])
});
var colM=new Ext.grid.ColumnModel([{header:" 项目名称 ",dataIndex:"name",sortable:true},
{header:" 开发团队 ",dataIndex:"organization",sortable:true},
{header:" 网址 ",dataIndex:"homepage",renderer:showUrl}]);
var grid = new Ext.grid.GridPanel({
renderTo:"hello",
title:" 中国 Java 开源产品及团队 ",
height:200,
600,
cm:colM,
store:store,
autoExpandColumn:2
});
store.load();
});
store.laod() 是用来加载数据,执行上面的代码产生的表格与前面的完全一样。
关于表格控件 GridPanel 的详细说明,请参考 wlr.easyjf.com 中的 VIP 文档《 ExtJS 表格 GridPanel 详 解 》。
7.2 、可编辑表格 EditorGridPanel
可 编辑表格是指可以直接在表格的单元格对表格的数据进行编辑, ExtJS 中的可编辑表格 由
类 Ext.grid.EditorGridPanel 表示, xtype 为 editorgrid 。使用 EditorGridPanel 与使用普通的
GridPanel 方式一样,区别只是在定义列信息的时候,可以指定某一列使用的编辑即可,下
面来看一个简单的示例。
Ext.onReady(function(){
var data=[{id:1,
name:' 小王 ',
email:'xiaowang@easyjf.com',
sex:' 男 ',
bornDate:'1991-4-4'},
{id:1,
name:' 小李 ',
email:'xiaoli@easyjf.com',
sex:' 男 ',
bornDate:'1992-5-6'},
{id:1,
name:' 小兰 ',
email:'xiaoxiao@easyjf.com',
sex:' 女 ',
bornDate:'1993-3-7'}
];
var store=new Ext.data.JsonStore({
data:data,
fields:["id","name","sex","email",{name:"bornDate",type:"date",dateFormat:"Y-n-j"}]
});
var colM=new Ext.grid.ColumnModel([{
header:" 姓名 ",
dataIndex:"name",
sortable:true,
editor:new Ext.form.TextField()},
{header:" 性别 ",
dataIndex:"sex"
},
{header:" 出生日期 ",
dataIndex:"bornDate",
120,
renderer:Ext.util.Format.dateRenderer('Y 年 m 月 d 日 ')},
{header:" 电子邮件 ",
dataIndex:"email",
sortable:true,
editor:new Ext.form.TextField()}
]);
var grid = new Ext.grid.EditorGridPanel({
renderTo:"hello",
title:" 学生基本信息管理 ",
height:200,
600,
cm:colM,
store:store,
autoExpandColumn:3
});
});
上面的程序首先定义了一个包含学生信息的对象数组,然后创建了一个 JsonStore ,在
创建这个 store 的时候,指定 bornDate 列的类型为日期 date 类型,并使用 dateFormat 来指 定
日期信息的格式为 "Y-n-j" , Y 代表年, n 代表月 ,j 代表日期。定义表格列模型的时候,对于 “ 姓
名 ” 及 “ 电子邮件 ” 列我们使用 editor 来定义该列使用的编辑器,这里是使用
Ext.form.TextField ,最后使用 new Ext.grid.EditorGridPanel( … ) 来创建一个可编辑的表格。执
行上面的程序可以生 成一个表格,双击表格中的 “ 姓名 ” 、或 “ 电子邮件 ” 单元格中的信息可 以
触发单元格的编辑,可以在单元格的文本框中直接编辑表格中的内容,修改过的单元格会 有
特殊的标记,如下图所示:
为了能编辑 “ 性别 ” 及 “ 出生日期 ” 列,同样只需要在定义该列的时候指定 editor 即可。 由
于出生日期是日期类型,因此我们可以使用日期编辑器来编辑, “ 性别 ” 一列的数据不应该 让
用户直接输入,而应该是通过下拉框进行选择。日期编辑器可以直接使用 Ext.form.DateFiel d
组件,下拉选择框编辑器可以使用 Ext.form.ComboBox 组件,下面是实现对性别及出生日 期
等列信息编辑的代码:
var colM=new Ext.grid.ColumnModel([{
header:" 姓名 ",
dataIndex:"name",
sortable:true,
editor:new Ext.form.TextField()},
{header:" 性别 ",
dataIndex:"sex",
editor:new Ext.form.ComboBox({transform:"sexList",
triggerAction: 'all',
lazyRender:true})
},
{header:" 出生日期 ",
dataIndex:"bornDate",
120,
renderer:Ext.util.Format.dateRenderer('Y 年 m 月 d 日 '),
editor:new Ext.form.DateField({format:'Y 年 m 月 d 日 '})},
{header:" 电子邮件 ",
dataIndex:"email",
sortable:true,
editor:new Ext.form.TextField()}
]);
var grid = new Ext.grid.EditorGridPanel({
renderTo:"hello",
title:" 学生基本信息管理 ",
height:200,
600,
cm:colM,
store:store,
autoExpandColumn:3,
clicksToEdit:1
});
注意在定义 EditorGridPanel 的时候,我们增加了一个属性 “ clicksToEdit:1 ” ,表示点击 一
次单元格即触发编辑,因为默认情况下该值为 2 ,需要双击单元格才能编辑。为了给
ComboBox 中填充数据,我们使用设置了该组件的 transform 配置属性值为 sexList , sexList
是一个传统的 <select> 框,我们需要在 html 页面中直接定义,代码如下:
<select>
<option> 男 </option>
<option> 女 </option>
</select>
执行上面的程序,我们可以得到一个能对表格中所有数据进行编辑的表格了。点击上 面
的 “ 性别 ” 一列的单元格时,会出现一个下拉选择框,点击 “ 出生日期 ” 一列的单元格时,会 出
现一个日期数据选择框,如图 xxxx 所示:
( 编辑性别列中的数据 )
( 编辑出生日期列中的数据 )
那么如何保存编辑后的数据呢?答案是直接使用 afteredit 事件。当对一个单元格进行 编
辑完之后,就会触发 afteredit 事件,可以通过该事件处理函数来处理单元格的信息编辑。 比
如在 http://wlr.easyjf.com/ 这个单用户 blog 示例中,当我们编辑一个日志目录的时候,需要
把编辑后的数据保存到服务器,代码如下:
this.grid.on("afteredit",this.afterEdit,this);
…
afterEdit:function(obj){
var r=obj.record;
var id=r.get("id");
var name=r.get("name");
var c=this.record2obj(r);
var tree=this.tree;
var node=tree.getSelectionModel().getSelectedNode();
if(node && node.id!="root")c.parentId=node.id;
if(id=="-1" && name!=""){
topicCategoryService.addTopicCategory(c,function(id){
if(id)r.set("id",id);
if(!node)node=tree.root;
node.appendChild(new Ext.tree.TreeNode({
id:id,
text:c.name,
leaf:true
}));
node.getUI().removeClass('x-tree-node-leaf');
node.getUI().addClass('x-tree-node-expanded');
node.expand();
});
}
else if(name!="")
{
topicCategoryService.updateTopicCategory(r.get("id"),c,function(ret){
if(ret)tree.getNodeById(r.get("id")).setText(c.name);
});
}
}
关于可编辑表格控件的详细说明,请参考 wlr.easyjf.com 中的 VIP 文档《 ExtJS 可编辑表格
EditorGridPanel 详解》。
7.3、与服务器交互
在 实际的应用中,表格中的数据一般都是直接存放在数据库表或服务器的文件中。因 此 ,
在使用表格控件的时候经常需要与服务器进行交互。 ExtJS 使用 Ajax 方式提供了一套与服 务
器交互的机制,也就是可以不用刷新页面,就可以访问服务器的程序进行数据读取或数据 保
存等操作。
比如前面在表格中显示 xml 文档中数据的例子中,就是一个非常简单的从服务器端读
取数据的例子,再回顾一下代码:
var store=new Ext.data.Store({
reader:new Ext.data.XmlReader({
record:"row"},
["id","name","organization","homepage"])
});
因为 Sote 组件接受一个参数 url ,如果设置 url ,则 ExtJS 会创建一个与服务器交互的
Ext.data.HttpProxy 对象,该对象通过指定的 Connection 或 Ext.Ajax.request 来向服务端发送
请求,从而可以读取到服务器端的数据。
经验表明,服务器端产生 JSon 数据是一种非常不错的选择,也就是说假如服务器的
url “ student.ejf?cmd=list ” 产生下面的 JSON 数据输出:
{results:[{id:1,
name:' 小王 ',
email:'xiaowang@easyjf.com',
sex:' 男 ',
bornDate:'1991-4-4'},
{id:1,
name:' 小李 ',
email:'xiaoli@easyjf.com',
sex:' 男 ',
bornDate:'1992-5-6'},
{id:1,
name:' 小兰 ',
email:'xiaoxiao@easyjf.com',
sex:' 女 ',
bornDate:'1993-3-7'}
] }
则前面显示学习信息编辑表格的 store 可以创建成下面的形式:
ar store=new Ext.data.Store({
reader:new Ext.data.JsonReader({
root:"result"},
["id","name","organization","homepage"])
});
或者:
var store=new Ext.data.JsonStore({
root:"result",
fields:["id","name","organization","homepage"]});
其中 root 表示包含记录集数据的属性。
如果在运行程序中需要给服务器端发送数据的时候,此时可以直接使用 ExtJS 中提供 的
Ext.Ajax 对象的 request 方法。比如下面的代码实现放服务器的 student.ejf?cmd=save 这个 ur l
发起一个请求,并在 params 中指定发送的 Student 对象:
var store=new Ext.data.JsonStore({
root:"result",
fields:["id","name","organization","homepage"]});
function sFn()
{
alert(' 保存成功 ');
}
function fFn()
{
alert(' 保存失败 ');
}
Ext.Ajax.request({
url: 'student.ejf?cmd=save ’
success: sFn
failure: fFn,
params: { name: ' 小李 ',email: ' xiaoli@easyjf.com',bornDate: ' 1992-5-6',sex: ' 男 '}
});
关于 ExtJS 中各控件与服务器端如何交互、 Ext.Ajax 的详细使用说明等请参考 wlr.easyjf.com 中的 VIP 文
档《 ExtJS 中客户端控件与服务器控件交互详解》。