- 浏览: 35741 次
- 性别:
- 来自: 广州
文章分类
最新评论
无论是界面之美,还是功能之强,ext的表格控件都高居榜首。
单选行,多选行,高亮显示选中的行,推拽改变列宽度,按列排序,这些基本功能咱们就不提了。
自动生成行号,支持checkbox全选,动态选择显示哪些列,支持本地以及远程分页,可以对单元格按照自己的想法进行渲染,这些也算可以想到的功能。
再加上可编辑grid,添加新行,删除一或多行,提示脏数据,推拽改变grid大小,grid之间推拽一或多行,甚至可以在tree和grid之间进行拖拽,啊,这些功能实在太神奇了。更令人惊叹的是,这些功能竟然都在ext表格控件里实现了。
呵呵~不过ext也不是万能的,与fins的ecside比较,ext不能锁定列(土豆说1.x里支持锁定列,但是2.0里没有了,因为影响效率。),也没有默认的统计功能,也不支持excel,pdf等导出数据。另外fins说,通过测试ecside的效率明显优于ext呢。:)
2.2. 让我们搞一个grid出来耍耍吧。
光说不练不是我们的传统,让我们基于examples里的例子,来自己搞一个grid看看效果,同时也可以知道一个grid到底需要配置些什么东西。
1.首先我们知道表格肯定是二维的,横着叫行,竖着叫列。跟设计数据库,新建表一样,我们要先设置这个表有几列,每列叫啥名字,啥类型,咋显示,这个表格的骨架也就出来了。
ext里,这个列的定义,叫做ColumnModel,简称cm的就是它,它作为整个表格的列模型,是要首先建立起来的。
这里我们建立一个三列的表格,第一列叫编号(code),第二列叫名称(name),第三列叫描述(descn)。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);看到了吧?非常简单的定义了三列,每列的header表示这列的名称,dataIndex是跟后面的东西对应的,咱们暂且不提。现在只要知道有了三列就可以了。
2.有了表格的骨架,现在我们要向里边添加数据了。这个数据当然也是二维了,为了简便,我们学习examples里的array-grid.js里的方式,把数据直接写到js里。
var data = [
['1','name1','descn1'],
['2','name2','descn2'],
['3','name3','descn3'],
['4','name4','descn4'],
['5','name5','descn5']
];很显然,我们这里定义了一个二维数据, (什么?你不知道这是二维数组?快改行吧,这里不是你该待的地方。)
这个有五条记录的二维数组,显示到grid里就应该是五行,每行三列,正好对应这id,name,descn,在我们的脑子里应该可以想像出grid显示的结果了,为了让想像变成显示,我们还需要对原始数据做一下转化。
3.因为咱们希望grid不只能支持array,还可以支持json,支持xml,甚至支持咱们自己定义的数据格式,ext为咱们提供了一个桥梁,Ext.data.Store,通过它我们可以把任何格式的数据转化成grid可以使用的形式,这样就不需要为每种数据格式写一个grid的实现了。现在咱们就来看看这个Ext.data.Store是如何转换array的。
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load();ds要对应两个部分:proxy和reader。proxy告诉我们从哪里获得数据,reader告诉我们如何解析这个数据。
现在我们用的是Ext.data.MemoryProxy,它是专门用来解析js变量的。你可以看到,我们直接把data作为参数传递进去了。
Ext.data.ArrayReader专门用来解析数组,并且告诉我们它会按照定义的规范进行解析,每行读取三个数据,第一个叫id,第二个叫name,第三个descn。是不是有些眼熟,翻到前面cm定义的地方,哦,原来跟dataIndex是对应的。这样cm就知道哪列应该显示那条数据了。唉,你要是能看明白这一点,那你实在是太聪明了。
记得要执行一次ds.load(),对数据进行初始化。
有兄弟可能要问了,要是我第一列数据不是id而是name,第二列数据不是name而是id咋办?嗯,嗯,这个使用就用mapping来解决。改改变成这样:
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id', mapping: 1},
{name: 'name', mapping: 0},
{name: 'descn', mapping: 2}
])
});
这样如截图所见,id和name两列的数据翻转了。如此这般,无论数据排列顺序如何,我们都可以使用mapping来控制对应关系,唯一需要注意的是,索引是从0开始的,所以对应第一列要写成mapping:0,以此类推。
4.哈哈,万事俱备只欠东风,表格的列模型定义好了,原始数据和数据的转换都做好了,剩下的只需要装配在一起,我们的grid就出来了。
var grid = new Ext.grid.Grid('grid', {
ds: ds,
cm: cm
});
grid.render();注意:上头是ext-1.x的写法,Ext.grid.Grid的第一个参数是渲染的id,对应在html里应该有一个 <div id="grid"></div>的东西,这样grid才知道要把自己画到哪里。
创建完grid以后,还要用grid.render()方法,让grid开始渲染,这样才能显示出来。
5.好了,把所有代码组合到一起,看看效果吧。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
var data = [
['1','name1','descn1'],
['2','name2','descn2'],
['3','name3','descn3'],
['4','name4','descn4'],
['5','name5','descn5']
];
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load();
var grid = new Ext.grid.Grid('grid', {
ds: ds,
cm: cm
});
grid.render();看看吧,这就是咱们搞出来的grid了。
html例子是lingo-sample/1.1.1目录下的02-01.html,把这个目录copy到ext-1.x的example目录下,就可以直接打开观看效果。
2.3. 上边那个是1.x的,2.0稍微有些不同哦
首先,Ext.grid.Grid已经不见了,咱们需要用Ext.grid.GridPanel。需要传递的参数也有少许区别。
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm
});看到了吗?负责指定渲染位置的id放到了{}里边,对应的名字是el。似乎ext2里对这些参数进行了统一,比以前更整齐了。
因为其他地方都一样,我就不多说了,html例子在是lingo-sample/2.0目录下的02-01.html。
从截图上看,少了斑马条,下边多了一条线,应该只是css有所不同吧。
默认情况下,两个版本的grid都可以拖拽列,也可以改变列的宽度。不知道怎么禁用这两个功能呢。
最大的不同应该是1.x里默认支持的右键效果,在2.0里不见了。
按shift和ctrl多选行的功能倒是都有。区别是,全选后,1.x必须按住ctrl才能取消,直接单击其中一个行,不会取消全选功能,而2.0里只需要任意点击一行,就取消全选,只选中刚才点击的那行。
哦,哦,那颜色不要也算是区别吧。
2.4. 按顺序,咱们先要把常见功能讲到,让grid支持按列排序
其实很简单,需要小小改动一下列模型。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id',sortable:true},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);如果你英语还可以,或者懂得查字典的话(软件翻译也算),那么你就会知道,多出来的这个sortable属性应该是可以排序的意思。现在咱们试一下改动后的效果。
看到了没有?编号的标题上有个小小的箭头,表格里的数据也是按照编号做的逆序排列,如此简单,我们就实现了按列排序。
很有趣的是,2.0加上sortable以后,1.x那种右键功能也跑回来了,不过它用的不是右键,而是下拉菜单似的实现方式。
什么?你问为什么其他两列无法排序?!嗯,好像是因为你还没有给另两列添加sortable属性。
怎么加?!按编号那样加就行了。
还是不会?!-_-。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id',sortable:true},
{header:'名称',dataIndex:'name',sortable:true},
{header:'描述',dataIndex:'descn',sortable:true}
]);这样所有列都可以排序了。什么?怎么取消排序?!-_-。
2.5. 让单元格里显示红色的字,图片,按钮,你还能想到什么?
嘿,希望你跟我一样,不愿意只能在grid里看到文字,至少不是单调的,毫无特色的文字。有些人就问了,如果我想改变一下单元格里显示内容,应该怎么办呢?
非常不幸的是,ext的作者,伟大的jack早已经想到了,说真的,你没想到的,他都想到了,不只想到了,他还做出来了。
唉,这就是区别啊。为啥你就不能动手做些东西呢?就知道向别人要这要那,唉。
首先,我宣布,偶们的数据要扩充啦,每个人要加上一个性别字段。
var data = [
['1','male','name1','descn1'],
['2','female','name2','descn2'],
['3','male','name3','descn3'],
['4','female','name4','descn4'],
['5','male','name5','descn5']
];男女搭配,干活不累撒。而且现在中国就是男多女少,我就还没对象呢。征婚中,单身女性加(QQ)771490531详谈。
你可以试试不改其他的部分,显示的结果是不会改变的,因为原始数据要经过ds的处理才能被grid使用,那么下一步我们就开始修改ds,把性别加进去。
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id'},
{name: 'sex'},
{name: 'name'},
{name: 'descn'}
])
});添加了一行{name: 'sex'},把数组的第二列映射为性别。现在grid可以感觉到sex了,嘿嘿。
不过grid还显示不了性别这列,因为咱们还没改cm。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);到现在其实都没什么新东西,但是你不觉得光看平板字,很难分出哪个是GG哪个是MM吗?听说过红男绿女没?要是男的都加上红色,女的都变成绿色,那不是清楚多了。就像下面一样。
怎么样?是不是效果大不同了。你不会认为很难吧,嗯,确实,如果你对html和css完全搞不明白的话,劝你还是先去学学吧,对自己有信心的往下看。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex',renderer:function(value){
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span>";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span>";
}
}},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);别被吓到,这么一大段其实就是判断是男是女,然后配上颜色。你要是觉得乱,也可以这么做。
function renderSex(value) {
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span>";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span>";
}
}
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex',renderer:renderSex},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);实际上这个renderer属性至关重要,它的值是一个function,哦,你说不知道js里function可以这么用?那么恭喜你,现在你知道了。
renderer会传递个参数进去,咱们grid里看到的,是这个函数的返回值,怎么样,神奇吧?
同志们,你们也应该看到了,返回html就可以,是html啊,html里有的东西,你返回什么就显示什么,颜色,链接,图片,按钮,只要你愿意,整个网页都可以返回回去。还有什么做不到的?哦,你不会html,那没辙,回去学吧。
咱们先来个图片。
function renderSex(value) {
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span><img src='user_male.png' />";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span><img src='user_female.png' />";
}
}是不是太简单了,下面咱们来玩点儿高级的。
function renderDescn(value, cellmeta, record, rowIndex, columnIndex, store) {
var str = "<input type='button' value='查看详细信息' onclick='alert(\"" +
"这个单元格的值是:" + value + "\\n" +
"这个单元格的配置是:{cellId:" + cellmeta.cellId + ",id:" + cellmeta.id + ",css:" + cellmeta.css + "}\\n" +
"这个单元格对应行的record是:" + record + ",一行的数据都在里边\\n" +
"这是第" + rowIndex + "行\\n" +
"这是第" + columnIndex + "列\\n" +
"这个表格对应的Ext.data.Store在这里:" + store + ",随便用吧。" +
"\")'>";
return str;
}来看看我们可以在render里用到多少参数:
1.value是当前单元格的值
2.cellmeta里保存的是cellId单元格id,id不知道是干啥的,似乎是列号,css是这个单元格的css样式。
3.record是这行的所有数据,你想要什么,record.data["id"]这样就获得了。
4.rowIndex是行号,不是从头往下数的意思,而是计算了分页以后的结果。
5.columnIndex列号太简单了。
6.store,这个厉害,实际上这个是你构造表格时候传递的ds,也就是说表格里所有的数据,你都可以随便调用,唉,太厉害了。
有个同学就问啦:EXT render的参数,是如何得到的呢。因为你讲的那些都是EXT自己内部的。它是如何把这些参数传递给render的呢?
这个问题其实比较简单,只是你们想复杂了。既然是函数,就肯定有调用它的地方,你找到GridView.js在里边搜索一下renderer,就会看到调用render的地方,这些参数都是在这里传进去的。
好,看看效果吧。
剩下的,就是发挥各位聪明才智的时候了,舞台已经搭好,看你如何表演了。
html例子,1.x版本在lingo-sample/1.1.1目录下的02-02.html,2.0的版本在lingo-sample/2.0目录下的02-02.html。
2.6. 更进一步,自动行号和多选checkbox
实际上行号和多选checkbox都是renderer的延伸,当然多选checkbox更酷一点儿,两者经常一起使用,所以让我们放在一起讨论好了。
2.6.1. 自动行号
只需要在cm中加上一行,这一行不会与ds中的任何数据对应,这也告诉我们可以凭空制作列,哈哈。
在之前的例子上改啦。
var cm = new Ext.grid.ColumnModel([
{header:'NO.',renderer:function(value, cellmeta, record, rowIndex){
return rowIndex + 1;
}},
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);如吾等所愿,不指定dataIndex,而是直接根据renderer返回rowIndex + 1,因为它是从0开始的,所以加个一。截图如下。
1.x的例子在lingo-sample/1.1.1/02-03.html
很遗憾的是,2.0里有自己的默认实现了,咱们不能展现自己的手工技艺了,还是乖乖使用jack提供的东东吧。
于是,在2.0里cm就变成了这幅模样。
var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);你绝对会同意我的意见,Jack's work is amazing.实在是太神奇了。看看截图就知道。
2.0的例子在lingo-sample/2.0/02-03.html
2.6.2. 全选checkbox的时间了,请允许我让2.0先上场。
因为2.0里有checkboxSelectionModel,这样完全可以证实用别人的轮子,比自己造轮子要方便。而且咱们造的轮子完全没有jack圆。不信的话,看下面1.x里的实现。
我们一直在修改cm,这次我们也要对它动刀了,不过SelectionModel既sm也要处理一下,这是为了改变单选和多选行的方式,以前这些可以靠shift或ctrl实现,而现在这些都要与checkbox关联上了。
啦啦啦,先看图片,后看代码。
先看看具体多了什么
var sm = new Ext.grid.CheckboxSelectionModel();神奇的是这个sm身兼两职,使用的时候既要放到cm里,也要放到grid中。代码如下。
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: 'grid',
ds: ds,
cm: cm,
sm: sm
});然后你就可以得到效果啦,代码在lingo-sample/2.0/02-04.html。
2.6.3. 1.x时代的全选checkbox。
理论上只需要给cm再加一列,像自动编号那样,不对应数据,只显示checkbox就可以了。难点就是checkbox与某一行被选择的时候要对应上,用checkbox选择上,sm里也要让这一行被选中,反之亦然。嗯,估计会比较复杂呢。
先放上显示checkbox的代码和截图:
var cm = new Ext.grid.ColumnModel([
{header:'NO.',renderer:function(value, cellmeta, record, rowIndex){
return rowIndex + 1;
}},
{header:'<input type="checkbox" onclick="selectAll(this)">',renderer:function(value, cellmeta, record, rowIndex){
return '<input type="checkbox" name="cb">';
}},
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
与sm对接的方面比较麻烦,好在extjs.com上已经有扩展了,或者你可以看看我们弄下来的。 看看1.x多选树的截图。
2.7. 分页了吗?分页了吗?如果还没分就看这里吧。
如果你有一千条信息,一次都输出到grid里,然后让客户用下拉条一点儿一点儿去找吧。我们这里可是要做一个分页效果了,不用滚动屏幕,或者滚动一下就可以看到本页显示的数据,如果想看其他的只需要翻页就可以了。同志们,加强客户体验呀。
实际上,grid控件挺耗性能的,据土豆讲一个页面上放3个grid就可以感觉到响应变慢,以前看过介绍,grid里显示数据过多,听说是上千条,也会明显变慢。
所以说分页是必不可少滴,而且jack提供了方便集成分页工具条的方式,不用一下实在是太浪费了。
两步走,让grid集成分页。
2.7.1. 表面工作,先把分页工具条弄出来。
从图片可以清晰的看到,在grid下边多出来一行东东,包括了前一页,后一页,第一页,最后一页,刷新,以及提示信息。而我们不过写了如下几行代码而已,神奇呀。
var gridFoot = grid.getView().getFooterPanel(true);
var paging = new Ext.PagingToolbar(gridFoot, ds, {
pageSize: 10,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: '没有记录'
});首先使用grid.getView().getFootPanel(true),获得grid下边那一条,嘿嘿,人家grid就设计的这么好,脚底下专门留了地方让你放东西。我们老实不客气,把Ext.PagingToolbar放到上边,就可以显示分页工具条了。
这分页工具条可不是个摆设,你按了前一页,后一页,整个grid都要有反应才对,要不咱们费劲弄这个么东西过来干嘛呀?所以,我们在构造PagingToolbar的时候,不但告诉它,在gridFoot上显示,还告诉它,进行分页跳转的时候,要对ds也进行操作。这个ds就是grid用来获取和显示数据的,它一变整个grid都发生变化,嘿嘿~这就算共享数据模型了。厉害呀。
知道了分页的玄机,让我们揉揉眼睛,好好看看里边的参数。
1.pageSize,是每页显示几条数据。
2.displayInfo,跟下面的配置有关,如果是false就不会显示提示信息。
3.displayMsg,只有在displayInfo:true的时候才有效,用来显示有数据的时候的提示信息,中国人应该看得懂汉语,到时候{0},{1},{2}会自动变成对应的数据,咱们只需要想办法把话说通就行了。
4.emptyMsg,要是没数据就显示这个,jack实在太贴心了,连这些小处都考虑得如此精细。
最好要注意的是,这段代码必须放在grid.render()之后,估计是因为动态生成grid的dom后,才能获得对应的footPanel。
现在给出例子,1.x的例子在lingo-sample/1.1.1/02-05.html。
2.7.2. 2.0赐予我们更大的灵活性
其实,在下,一直,对于:必须先渲染grid才能获得footPanel这事非常愤恨,你想啊,本来分页也应该属于初始化的一部分,现在却要先初始化grid,配置完毕,渲染,回过头来再从grid里把footPanel拿出来,再咕哝分页的配置。真,真,真郁闷呀。
所以2.0里的方式,简直大快民心。
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm,
bbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: "没有记录"
})
});
ds.load();嘿嘿,加一个bbar的参数就可以了,bbar就是bottom bar啦,底端工具条。
不过还是要注意一点,与1.x中不同的是,如果配置了分页工具条,ds.load()就必须在构造grid以后才能执行,否则分页工具条会不起作用。看来分页工具条会把自己和ds做一些关联,来完成与grid共享数据模型的。
对了,还有一点不同,1.x中分页条不会随着浏览器的大小改变,自动放缩,这点在2.0中也解决了。
2.0的例子在lingo-sample/2.0/02-05.html。
2.7.3. 迫不得已,要加上后台脚本了。
grid会每次都显示ds中所有的数据,咱们没法利用静态数据好好演示分页,于是,必须写后台脚本,让ext与后台进行数据交互才能看到真实的分页效果。
咱们尽量在原来的基础上修改啊,把注意力集中在关键部位,一次性突破。
我不会其他语言,后台就用jsp写啦。有个好消息是只要返回的数据格式一样,ext才不管后台是什么写的呢。也就是这样,不管你以后用什么实现后台,前台的ext代码都一样。
<%
String start = request.getParameter("start");
String limit = request.getParameter("limit");
try {
int index = Integer.parseInt(start);
int pageSize = Integer.parseInt(limit);
String json = "{totalProperty:100,root:[";
for (int i = index; i < pageSize + index; i++) {
json += "{id:" + i + ",name:'name" + i + "',descn:'descn" + i + "'}";
if (i != pageSize + index - 1) {
json += ",";
}
}
json += "]}";
response.getWriter().write(json);
} catch(Exception ex) {
}
%>下面我们来解读这段jsp代码:
1.在进行操作之前,我们先要获得ext传递过来的两个参数:start和limit,start指的从第几个数据开始显示,limit是说从start开始,一共要用多少个数据,当然返回的数据可能会小于这个值。
2.咱们在后台模拟对100条数据进行分页,在获得了start和limit之后再生成json格式的数据。
何谓json?在理论讲解之前先看看实例,让我们能有个感性认识,至于以后能不能升华到理性认识,就看各位的悟性了。
模拟ext访问后台,并传递两个参数start=0&limit=10,把获得的数据稍微整理一下,是这个样子。
{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'}
]}请记住这个数据格式,不管后台是什么,只要满足了这样的格式要求,ext就可以接收处理,显示到grid中。
我这里就不好好介绍json,现在只需要知道json里头除了name(名称)就是value(值),值有好几种格式,如果是数字就不用加引号,如果加了引号就是字符串,如果用[]包裹就是数组,如果出现{}就说明是嵌套的json。诸如此类。
简单瞄了json一眼,开头就是totalProperty:100,这告诉ext:“俺这里有100个数据呢。”,然后就是root:[],root对应着一个数组,数组里有10个对象,每个对象都有id呀,name呀,descn呀。这10个数据最后就应该显示到表格里。
3.jsp里用for循环生成root数组里的数据,这样我们翻页的时候可以看到数据的变化,要不每次都是一样的数据,你怎么知道翻页是不是起作用了呢?
最后我们把得到的json字符串输出到response里,ext也就可以获得这些数据了。
结果经过了一番折腾,我们的jsp已经确定可以返回我们所需要的数据了。现在我们可以忘掉后台是用什么语言写的了,直接切入ext代码,看看它是怎么样才能跑去后台获得这些数据呢?
因为引入了json作为数据传输格式,这次我们要对ext代码进行一次大换血了,请做好思想准备。
1.换掉proxy,别在内存里找了,让我们通过http获得我们想要的。
proxy: new Ext.data.HttpProxy({url:'grid.jsp'}),创建HttpProxy的同时,用url这个参数指定咱们去哪里取数据,我们这里设置成grid.jsp,就是我们刚才讨论的jsp脚本啦。
2.已经不是数组了,现在要用json咯。
reader: new Ext.data.JsonReader({
totalProperty: 'totalProperty',
root: 'root'
}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])看比ArrayReader多了什么?totalProperty对应咱们jsp返回的totalProperty,也就是数据的总数。root对应咱们jsp返回的root,就是一个包含返回数据的数组。
3.好了,最后在初始化的时候,告诉我们希望获得哪部分的数据就可以了。
ds.load({params:{start:0,limit:10}});就在ds读取的时候添加两个参数,start和limit,告诉后台,我们从第一个数可以取起,最多要10个。
在这里有一个小插曲,如果你按照我们以前的设置,grid是无法正常显示的,因为ds.load()无法在grid.render()前准备好所有数组,所以它不知道自己应该实现多高。没法子,我们只好为它指定一个固定的高度了。像这样<div id="grid" style="height:265px;"></div>。
最后,我们就可以使用分页条上那些按钮试试分页了。呵呵~就这么简单。
1.x的例子在lingo-sample/1.1.1/02-06.html,jsp文件在lingo-sample/1.1.1/grid.jsp,下面是它的截图:
有趣的是,1.x中,不需要为div指定高度,它自己就知道如何显示,不晓得为什么2.0里不这样做呢。
2.0的例子在lingo-sample/2.0/02-06.html,jsp文件在lingo-sample/2.0/grid.jsp,下面是它的截图:
2.7.4. 其实分页不一定要踩在脚下,也可以顶在头上。
我的意思是,grid除了FootPanel以外,还有HeaderPanel,意思就是头顶上的面板。我们把分页条放在上面也不会有任何问题。1.x中的代码仅仅是将getFooterPanel改成getHeaderPanel,这样分页条就跑到上头去了。
var gridHead = grid.getView().getHeaderPanel(true);
var paging = new Ext.PagingToolbar(gridHead, ds, {
pageSize: 10,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: '没有记录'
});
1.x的例子可以在lingo-sample/1.1.1/02-07.html找到。
2.0就更简单了,只需要改一个字母,b -> t,呵呵~,让原来的bbar(bottom bar)变成tbar(top bar)就可以让我们的工具条登天了。
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm,
tbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: "没有记录"
})
});
单选行,多选行,高亮显示选中的行,推拽改变列宽度,按列排序,这些基本功能咱们就不提了。
自动生成行号,支持checkbox全选,动态选择显示哪些列,支持本地以及远程分页,可以对单元格按照自己的想法进行渲染,这些也算可以想到的功能。
再加上可编辑grid,添加新行,删除一或多行,提示脏数据,推拽改变grid大小,grid之间推拽一或多行,甚至可以在tree和grid之间进行拖拽,啊,这些功能实在太神奇了。更令人惊叹的是,这些功能竟然都在ext表格控件里实现了。
呵呵~不过ext也不是万能的,与fins的ecside比较,ext不能锁定列(土豆说1.x里支持锁定列,但是2.0里没有了,因为影响效率。),也没有默认的统计功能,也不支持excel,pdf等导出数据。另外fins说,通过测试ecside的效率明显优于ext呢。:)
2.2. 让我们搞一个grid出来耍耍吧。
光说不练不是我们的传统,让我们基于examples里的例子,来自己搞一个grid看看效果,同时也可以知道一个grid到底需要配置些什么东西。
1.首先我们知道表格肯定是二维的,横着叫行,竖着叫列。跟设计数据库,新建表一样,我们要先设置这个表有几列,每列叫啥名字,啥类型,咋显示,这个表格的骨架也就出来了。
ext里,这个列的定义,叫做ColumnModel,简称cm的就是它,它作为整个表格的列模型,是要首先建立起来的。
这里我们建立一个三列的表格,第一列叫编号(code),第二列叫名称(name),第三列叫描述(descn)。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);看到了吧?非常简单的定义了三列,每列的header表示这列的名称,dataIndex是跟后面的东西对应的,咱们暂且不提。现在只要知道有了三列就可以了。
2.有了表格的骨架,现在我们要向里边添加数据了。这个数据当然也是二维了,为了简便,我们学习examples里的array-grid.js里的方式,把数据直接写到js里。
var data = [
['1','name1','descn1'],
['2','name2','descn2'],
['3','name3','descn3'],
['4','name4','descn4'],
['5','name5','descn5']
];很显然,我们这里定义了一个二维数据, (什么?你不知道这是二维数组?快改行吧,这里不是你该待的地方。)
这个有五条记录的二维数组,显示到grid里就应该是五行,每行三列,正好对应这id,name,descn,在我们的脑子里应该可以想像出grid显示的结果了,为了让想像变成显示,我们还需要对原始数据做一下转化。
3.因为咱们希望grid不只能支持array,还可以支持json,支持xml,甚至支持咱们自己定义的数据格式,ext为咱们提供了一个桥梁,Ext.data.Store,通过它我们可以把任何格式的数据转化成grid可以使用的形式,这样就不需要为每种数据格式写一个grid的实现了。现在咱们就来看看这个Ext.data.Store是如何转换array的。
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load();ds要对应两个部分:proxy和reader。proxy告诉我们从哪里获得数据,reader告诉我们如何解析这个数据。
现在我们用的是Ext.data.MemoryProxy,它是专门用来解析js变量的。你可以看到,我们直接把data作为参数传递进去了。
Ext.data.ArrayReader专门用来解析数组,并且告诉我们它会按照定义的规范进行解析,每行读取三个数据,第一个叫id,第二个叫name,第三个descn。是不是有些眼熟,翻到前面cm定义的地方,哦,原来跟dataIndex是对应的。这样cm就知道哪列应该显示那条数据了。唉,你要是能看明白这一点,那你实在是太聪明了。
记得要执行一次ds.load(),对数据进行初始化。
有兄弟可能要问了,要是我第一列数据不是id而是name,第二列数据不是name而是id咋办?嗯,嗯,这个使用就用mapping来解决。改改变成这样:
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id', mapping: 1},
{name: 'name', mapping: 0},
{name: 'descn', mapping: 2}
])
});
这样如截图所见,id和name两列的数据翻转了。如此这般,无论数据排列顺序如何,我们都可以使用mapping来控制对应关系,唯一需要注意的是,索引是从0开始的,所以对应第一列要写成mapping:0,以此类推。
4.哈哈,万事俱备只欠东风,表格的列模型定义好了,原始数据和数据的转换都做好了,剩下的只需要装配在一起,我们的grid就出来了。
var grid = new Ext.grid.Grid('grid', {
ds: ds,
cm: cm
});
grid.render();注意:上头是ext-1.x的写法,Ext.grid.Grid的第一个参数是渲染的id,对应在html里应该有一个 <div id="grid"></div>的东西,这样grid才知道要把自己画到哪里。
创建完grid以后,还要用grid.render()方法,让grid开始渲染,这样才能显示出来。
5.好了,把所有代码组合到一起,看看效果吧。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
var data = [
['1','name1','descn1'],
['2','name2','descn2'],
['3','name3','descn3'],
['4','name4','descn4'],
['5','name5','descn5']
];
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])
});
ds.load();
var grid = new Ext.grid.Grid('grid', {
ds: ds,
cm: cm
});
grid.render();看看吧,这就是咱们搞出来的grid了。
html例子是lingo-sample/1.1.1目录下的02-01.html,把这个目录copy到ext-1.x的example目录下,就可以直接打开观看效果。
2.3. 上边那个是1.x的,2.0稍微有些不同哦
首先,Ext.grid.Grid已经不见了,咱们需要用Ext.grid.GridPanel。需要传递的参数也有少许区别。
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm
});看到了吗?负责指定渲染位置的id放到了{}里边,对应的名字是el。似乎ext2里对这些参数进行了统一,比以前更整齐了。
因为其他地方都一样,我就不多说了,html例子在是lingo-sample/2.0目录下的02-01.html。
从截图上看,少了斑马条,下边多了一条线,应该只是css有所不同吧。
默认情况下,两个版本的grid都可以拖拽列,也可以改变列的宽度。不知道怎么禁用这两个功能呢。
最大的不同应该是1.x里默认支持的右键效果,在2.0里不见了。
按shift和ctrl多选行的功能倒是都有。区别是,全选后,1.x必须按住ctrl才能取消,直接单击其中一个行,不会取消全选功能,而2.0里只需要任意点击一行,就取消全选,只选中刚才点击的那行。
哦,哦,那颜色不要也算是区别吧。
2.4. 按顺序,咱们先要把常见功能讲到,让grid支持按列排序
其实很简单,需要小小改动一下列模型。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id',sortable:true},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);如果你英语还可以,或者懂得查字典的话(软件翻译也算),那么你就会知道,多出来的这个sortable属性应该是可以排序的意思。现在咱们试一下改动后的效果。
看到了没有?编号的标题上有个小小的箭头,表格里的数据也是按照编号做的逆序排列,如此简单,我们就实现了按列排序。
很有趣的是,2.0加上sortable以后,1.x那种右键功能也跑回来了,不过它用的不是右键,而是下拉菜单似的实现方式。
什么?你问为什么其他两列无法排序?!嗯,好像是因为你还没有给另两列添加sortable属性。
怎么加?!按编号那样加就行了。
还是不会?!-_-。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id',sortable:true},
{header:'名称',dataIndex:'name',sortable:true},
{header:'描述',dataIndex:'descn',sortable:true}
]);这样所有列都可以排序了。什么?怎么取消排序?!-_-。
2.5. 让单元格里显示红色的字,图片,按钮,你还能想到什么?
嘿,希望你跟我一样,不愿意只能在grid里看到文字,至少不是单调的,毫无特色的文字。有些人就问了,如果我想改变一下单元格里显示内容,应该怎么办呢?
非常不幸的是,ext的作者,伟大的jack早已经想到了,说真的,你没想到的,他都想到了,不只想到了,他还做出来了。
唉,这就是区别啊。为啥你就不能动手做些东西呢?就知道向别人要这要那,唉。
首先,我宣布,偶们的数据要扩充啦,每个人要加上一个性别字段。
var data = [
['1','male','name1','descn1'],
['2','female','name2','descn2'],
['3','male','name3','descn3'],
['4','female','name4','descn4'],
['5','male','name5','descn5']
];男女搭配,干活不累撒。而且现在中国就是男多女少,我就还没对象呢。征婚中,单身女性加(QQ)771490531详谈。
你可以试试不改其他的部分,显示的结果是不会改变的,因为原始数据要经过ds的处理才能被grid使用,那么下一步我们就开始修改ds,把性别加进去。
var ds = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(data),
reader: new Ext.data.ArrayReader({}, [
{name: 'id'},
{name: 'sex'},
{name: 'name'},
{name: 'descn'}
])
});添加了一行{name: 'sex'},把数组的第二列映射为性别。现在grid可以感觉到sex了,嘿嘿。
不过grid还显示不了性别这列,因为咱们还没改cm。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);到现在其实都没什么新东西,但是你不觉得光看平板字,很难分出哪个是GG哪个是MM吗?听说过红男绿女没?要是男的都加上红色,女的都变成绿色,那不是清楚多了。就像下面一样。
怎么样?是不是效果大不同了。你不会认为很难吧,嗯,确实,如果你对html和css完全搞不明白的话,劝你还是先去学学吧,对自己有信心的往下看。
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex',renderer:function(value){
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span>";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span>";
}
}},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);别被吓到,这么一大段其实就是判断是男是女,然后配上颜色。你要是觉得乱,也可以这么做。
function renderSex(value) {
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span>";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span>";
}
}
var cm = new Ext.grid.ColumnModel([
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex',renderer:renderSex},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);实际上这个renderer属性至关重要,它的值是一个function,哦,你说不知道js里function可以这么用?那么恭喜你,现在你知道了。
renderer会传递个参数进去,咱们grid里看到的,是这个函数的返回值,怎么样,神奇吧?
同志们,你们也应该看到了,返回html就可以,是html啊,html里有的东西,你返回什么就显示什么,颜色,链接,图片,按钮,只要你愿意,整个网页都可以返回回去。还有什么做不到的?哦,你不会html,那没辙,回去学吧。
咱们先来个图片。
function renderSex(value) {
if (value == 'male') {
return "<span style='color:red;font-weight:bold;'>红男</span><img src='user_male.png' />";
} else {
return "<span style='color:green;font-weight:bold;'>绿女</span><img src='user_female.png' />";
}
}是不是太简单了,下面咱们来玩点儿高级的。
function renderDescn(value, cellmeta, record, rowIndex, columnIndex, store) {
var str = "<input type='button' value='查看详细信息' onclick='alert(\"" +
"这个单元格的值是:" + value + "\\n" +
"这个单元格的配置是:{cellId:" + cellmeta.cellId + ",id:" + cellmeta.id + ",css:" + cellmeta.css + "}\\n" +
"这个单元格对应行的record是:" + record + ",一行的数据都在里边\\n" +
"这是第" + rowIndex + "行\\n" +
"这是第" + columnIndex + "列\\n" +
"这个表格对应的Ext.data.Store在这里:" + store + ",随便用吧。" +
"\")'>";
return str;
}来看看我们可以在render里用到多少参数:
1.value是当前单元格的值
2.cellmeta里保存的是cellId单元格id,id不知道是干啥的,似乎是列号,css是这个单元格的css样式。
3.record是这行的所有数据,你想要什么,record.data["id"]这样就获得了。
4.rowIndex是行号,不是从头往下数的意思,而是计算了分页以后的结果。
5.columnIndex列号太简单了。
6.store,这个厉害,实际上这个是你构造表格时候传递的ds,也就是说表格里所有的数据,你都可以随便调用,唉,太厉害了。
有个同学就问啦:EXT render的参数,是如何得到的呢。因为你讲的那些都是EXT自己内部的。它是如何把这些参数传递给render的呢?
这个问题其实比较简单,只是你们想复杂了。既然是函数,就肯定有调用它的地方,你找到GridView.js在里边搜索一下renderer,就会看到调用render的地方,这些参数都是在这里传进去的。
好,看看效果吧。
剩下的,就是发挥各位聪明才智的时候了,舞台已经搭好,看你如何表演了。
html例子,1.x版本在lingo-sample/1.1.1目录下的02-02.html,2.0的版本在lingo-sample/2.0目录下的02-02.html。
2.6. 更进一步,自动行号和多选checkbox
实际上行号和多选checkbox都是renderer的延伸,当然多选checkbox更酷一点儿,两者经常一起使用,所以让我们放在一起讨论好了。
2.6.1. 自动行号
只需要在cm中加上一行,这一行不会与ds中的任何数据对应,这也告诉我们可以凭空制作列,哈哈。
在之前的例子上改啦。
var cm = new Ext.grid.ColumnModel([
{header:'NO.',renderer:function(value, cellmeta, record, rowIndex){
return rowIndex + 1;
}},
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);如吾等所愿,不指定dataIndex,而是直接根据renderer返回rowIndex + 1,因为它是从0开始的,所以加个一。截图如下。
1.x的例子在lingo-sample/1.1.1/02-03.html
很遗憾的是,2.0里有自己的默认实现了,咱们不能展现自己的手工技艺了,还是乖乖使用jack提供的东东吧。
于是,在2.0里cm就变成了这幅模样。
var cm = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);你绝对会同意我的意见,Jack's work is amazing.实在是太神奇了。看看截图就知道。
2.0的例子在lingo-sample/2.0/02-03.html
2.6.2. 全选checkbox的时间了,请允许我让2.0先上场。
因为2.0里有checkboxSelectionModel,这样完全可以证实用别人的轮子,比自己造轮子要方便。而且咱们造的轮子完全没有jack圆。不信的话,看下面1.x里的实现。
我们一直在修改cm,这次我们也要对它动刀了,不过SelectionModel既sm也要处理一下,这是为了改变单选和多选行的方式,以前这些可以靠shift或ctrl实现,而现在这些都要与checkbox关联上了。
啦啦啦,先看图片,后看代码。
先看看具体多了什么
var sm = new Ext.grid.CheckboxSelectionModel();神奇的是这个sm身兼两职,使用的时候既要放到cm里,也要放到grid中。代码如下。
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: 'grid',
ds: ds,
cm: cm,
sm: sm
});然后你就可以得到效果啦,代码在lingo-sample/2.0/02-04.html。
2.6.3. 1.x时代的全选checkbox。
理论上只需要给cm再加一列,像自动编号那样,不对应数据,只显示checkbox就可以了。难点就是checkbox与某一行被选择的时候要对应上,用checkbox选择上,sm里也要让这一行被选中,反之亦然。嗯,估计会比较复杂呢。
先放上显示checkbox的代码和截图:
var cm = new Ext.grid.ColumnModel([
{header:'NO.',renderer:function(value, cellmeta, record, rowIndex){
return rowIndex + 1;
}},
{header:'<input type="checkbox" onclick="selectAll(this)">',renderer:function(value, cellmeta, record, rowIndex){
return '<input type="checkbox" name="cb">';
}},
{header:'编号',dataIndex:'id'},
{header:'性别',dataIndex:'sex'},
{header:'名称',dataIndex:'name'},
{header:'描述',dataIndex:'descn'}
]);
与sm对接的方面比较麻烦,好在extjs.com上已经有扩展了,或者你可以看看我们弄下来的。 看看1.x多选树的截图。
2.7. 分页了吗?分页了吗?如果还没分就看这里吧。
如果你有一千条信息,一次都输出到grid里,然后让客户用下拉条一点儿一点儿去找吧。我们这里可是要做一个分页效果了,不用滚动屏幕,或者滚动一下就可以看到本页显示的数据,如果想看其他的只需要翻页就可以了。同志们,加强客户体验呀。
实际上,grid控件挺耗性能的,据土豆讲一个页面上放3个grid就可以感觉到响应变慢,以前看过介绍,grid里显示数据过多,听说是上千条,也会明显变慢。
所以说分页是必不可少滴,而且jack提供了方便集成分页工具条的方式,不用一下实在是太浪费了。
两步走,让grid集成分页。
2.7.1. 表面工作,先把分页工具条弄出来。
从图片可以清晰的看到,在grid下边多出来一行东东,包括了前一页,后一页,第一页,最后一页,刷新,以及提示信息。而我们不过写了如下几行代码而已,神奇呀。
var gridFoot = grid.getView().getFooterPanel(true);
var paging = new Ext.PagingToolbar(gridFoot, ds, {
pageSize: 10,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: '没有记录'
});首先使用grid.getView().getFootPanel(true),获得grid下边那一条,嘿嘿,人家grid就设计的这么好,脚底下专门留了地方让你放东西。我们老实不客气,把Ext.PagingToolbar放到上边,就可以显示分页工具条了。
这分页工具条可不是个摆设,你按了前一页,后一页,整个grid都要有反应才对,要不咱们费劲弄这个么东西过来干嘛呀?所以,我们在构造PagingToolbar的时候,不但告诉它,在gridFoot上显示,还告诉它,进行分页跳转的时候,要对ds也进行操作。这个ds就是grid用来获取和显示数据的,它一变整个grid都发生变化,嘿嘿~这就算共享数据模型了。厉害呀。
知道了分页的玄机,让我们揉揉眼睛,好好看看里边的参数。
1.pageSize,是每页显示几条数据。
2.displayInfo,跟下面的配置有关,如果是false就不会显示提示信息。
3.displayMsg,只有在displayInfo:true的时候才有效,用来显示有数据的时候的提示信息,中国人应该看得懂汉语,到时候{0},{1},{2}会自动变成对应的数据,咱们只需要想办法把话说通就行了。
4.emptyMsg,要是没数据就显示这个,jack实在太贴心了,连这些小处都考虑得如此精细。
最好要注意的是,这段代码必须放在grid.render()之后,估计是因为动态生成grid的dom后,才能获得对应的footPanel。
现在给出例子,1.x的例子在lingo-sample/1.1.1/02-05.html。
2.7.2. 2.0赐予我们更大的灵活性
其实,在下,一直,对于:必须先渲染grid才能获得footPanel这事非常愤恨,你想啊,本来分页也应该属于初始化的一部分,现在却要先初始化grid,配置完毕,渲染,回过头来再从grid里把footPanel拿出来,再咕哝分页的配置。真,真,真郁闷呀。
所以2.0里的方式,简直大快民心。
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm,
bbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: "没有记录"
})
});
ds.load();嘿嘿,加一个bbar的参数就可以了,bbar就是bottom bar啦,底端工具条。
不过还是要注意一点,与1.x中不同的是,如果配置了分页工具条,ds.load()就必须在构造grid以后才能执行,否则分页工具条会不起作用。看来分页工具条会把自己和ds做一些关联,来完成与grid共享数据模型的。
对了,还有一点不同,1.x中分页条不会随着浏览器的大小改变,自动放缩,这点在2.0中也解决了。
2.0的例子在lingo-sample/2.0/02-05.html。
2.7.3. 迫不得已,要加上后台脚本了。
grid会每次都显示ds中所有的数据,咱们没法利用静态数据好好演示分页,于是,必须写后台脚本,让ext与后台进行数据交互才能看到真实的分页效果。
咱们尽量在原来的基础上修改啊,把注意力集中在关键部位,一次性突破。
我不会其他语言,后台就用jsp写啦。有个好消息是只要返回的数据格式一样,ext才不管后台是什么写的呢。也就是这样,不管你以后用什么实现后台,前台的ext代码都一样。
<%
String start = request.getParameter("start");
String limit = request.getParameter("limit");
try {
int index = Integer.parseInt(start);
int pageSize = Integer.parseInt(limit);
String json = "{totalProperty:100,root:[";
for (int i = index; i < pageSize + index; i++) {
json += "{id:" + i + ",name:'name" + i + "',descn:'descn" + i + "'}";
if (i != pageSize + index - 1) {
json += ",";
}
}
json += "]}";
response.getWriter().write(json);
} catch(Exception ex) {
}
%>下面我们来解读这段jsp代码:
1.在进行操作之前,我们先要获得ext传递过来的两个参数:start和limit,start指的从第几个数据开始显示,limit是说从start开始,一共要用多少个数据,当然返回的数据可能会小于这个值。
2.咱们在后台模拟对100条数据进行分页,在获得了start和limit之后再生成json格式的数据。
何谓json?在理论讲解之前先看看实例,让我们能有个感性认识,至于以后能不能升华到理性认识,就看各位的悟性了。
模拟ext访问后台,并传递两个参数start=0&limit=10,把获得的数据稍微整理一下,是这个样子。
{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'}
]}请记住这个数据格式,不管后台是什么,只要满足了这样的格式要求,ext就可以接收处理,显示到grid中。
我这里就不好好介绍json,现在只需要知道json里头除了name(名称)就是value(值),值有好几种格式,如果是数字就不用加引号,如果加了引号就是字符串,如果用[]包裹就是数组,如果出现{}就说明是嵌套的json。诸如此类。
简单瞄了json一眼,开头就是totalProperty:100,这告诉ext:“俺这里有100个数据呢。”,然后就是root:[],root对应着一个数组,数组里有10个对象,每个对象都有id呀,name呀,descn呀。这10个数据最后就应该显示到表格里。
3.jsp里用for循环生成root数组里的数据,这样我们翻页的时候可以看到数据的变化,要不每次都是一样的数据,你怎么知道翻页是不是起作用了呢?
最后我们把得到的json字符串输出到response里,ext也就可以获得这些数据了。
结果经过了一番折腾,我们的jsp已经确定可以返回我们所需要的数据了。现在我们可以忘掉后台是用什么语言写的了,直接切入ext代码,看看它是怎么样才能跑去后台获得这些数据呢?
因为引入了json作为数据传输格式,这次我们要对ext代码进行一次大换血了,请做好思想准备。
1.换掉proxy,别在内存里找了,让我们通过http获得我们想要的。
proxy: new Ext.data.HttpProxy({url:'grid.jsp'}),创建HttpProxy的同时,用url这个参数指定咱们去哪里取数据,我们这里设置成grid.jsp,就是我们刚才讨论的jsp脚本啦。
2.已经不是数组了,现在要用json咯。
reader: new Ext.data.JsonReader({
totalProperty: 'totalProperty',
root: 'root'
}, [
{name: 'id'},
{name: 'name'},
{name: 'descn'}
])看比ArrayReader多了什么?totalProperty对应咱们jsp返回的totalProperty,也就是数据的总数。root对应咱们jsp返回的root,就是一个包含返回数据的数组。
3.好了,最后在初始化的时候,告诉我们希望获得哪部分的数据就可以了。
ds.load({params:{start:0,limit:10}});就在ds读取的时候添加两个参数,start和limit,告诉后台,我们从第一个数可以取起,最多要10个。
在这里有一个小插曲,如果你按照我们以前的设置,grid是无法正常显示的,因为ds.load()无法在grid.render()前准备好所有数组,所以它不知道自己应该实现多高。没法子,我们只好为它指定一个固定的高度了。像这样<div id="grid" style="height:265px;"></div>。
最后,我们就可以使用分页条上那些按钮试试分页了。呵呵~就这么简单。
1.x的例子在lingo-sample/1.1.1/02-06.html,jsp文件在lingo-sample/1.1.1/grid.jsp,下面是它的截图:
有趣的是,1.x中,不需要为div指定高度,它自己就知道如何显示,不晓得为什么2.0里不这样做呢。
2.0的例子在lingo-sample/2.0/02-06.html,jsp文件在lingo-sample/2.0/grid.jsp,下面是它的截图:
2.7.4. 其实分页不一定要踩在脚下,也可以顶在头上。
我的意思是,grid除了FootPanel以外,还有HeaderPanel,意思就是头顶上的面板。我们把分页条放在上面也不会有任何问题。1.x中的代码仅仅是将getFooterPanel改成getHeaderPanel,这样分页条就跑到上头去了。
var gridHead = grid.getView().getHeaderPanel(true);
var paging = new Ext.PagingToolbar(gridHead, ds, {
pageSize: 10,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: '没有记录'
});
1.x的例子可以在lingo-sample/1.1.1/02-07.html找到。
2.0就更简单了,只需要改一个字母,b -> t,呵呵~,让原来的bbar(bottom bar)变成tbar(top bar)就可以让我们的工具条登天了。
var grid = new Ext.grid.GridPanel({
el: 'grid',
ds: ds,
cm: cm,
tbar: new Ext.PagingToolbar({
pageSize: 10,
store: ds,
displayInfo: true,
displayMsg: '显示第 {0} 条到 {1} 条记录,一共 {2} 条',
emptyMsg: "没有记录"
})
});
相关推荐
在描述中提到的“表格实现报表格式”,这是EXT JS的核心功能之一,通过表格来组织和展示数据,使其更易于理解。 EXT JS的报表系统支持多种高级特性,包括: 1. **表头分割**:EXT JS允许开发者将表头进行多级拆分...
Ext JS提供了`Ext.MessageBox`,可以轻松创建各种类型的对话框: ```javascript Ext.MessageBox.show({ title: '提示', msg: '确认要删除吗?', buttons: Ext.Msg.YESNO, fn: function(buttonId, text, opt) {...
在网页设计中,表格是一种常见的布局方式,用于展示结构化数据。然而,传统的HTML `<table>` 元素在样式控制上可能较为有限,有时我们希望获得更灵活的布局和更丰富的设计效果。这就是"ul打造表格样式"这个主题所...
EXT Grid和Panel等组件可以自动调整大小和排列方式,以适应各种屏幕尺寸。 6. 扩展性和模块化: EXT采用MVC(Model-View-Controller)架构模式,使得代码组织清晰,易于维护和扩展。EXT的应用通常由多个可复用的...
通过调用`Ext.MessageBox.show`方法,你可以设置各种属性,如`msg`(消息文本),`buttons`(按钮配置)和`icon`(图标类型)。 进度条效果在EXTJS中可以通过`Ext.ProgressBar`组件实现。这个组件可以实时展示任务...
开发者可以更直观地理解EXT4.1.0的各种功能和接口,从而提高开发效率。 EXT中文API V0.7的核心特性包括: 1. **组件化**:EXT提供了大量的预定义组件,如按钮、表格、表单、面板等,这些组件都是可重用的,可以...
### Extjs4.2 入门详细文档及表格初级制作 #### 一、Extjs4.2 下载与安装 **1.1 Extjs4.2 文件结构介绍** 初次接触到Extjs4.2的同学可能会对下载下来的文件夹结构感到困惑。下面我们将详细解释各个目录的作用: ...
"Ext的图书管理系统"显然利用了ExtJS的强大功能,为用户提供了一个直观且美观的界面来管理和操作图书数据。在这个系统中,用户可以轻松地进行图书的添加、删除、修改以及查询等操作,极大地提高了图书管理的效率。 ...
EXT2.2 API的核心在于其强大的组件系统,包括表格、网格、面板、窗口、菜单等,这些组件具有高度可定制性和交互性,能够满足各种复杂应用的需求。 LocalHXR.js是基于EXT2.2 API的一款本地JavaScript代码,它的出现...
EXT JS(EXT的早期版本称为EXT JS,后来更名为Sencha EXT JS)提供了一套完整的、可自定义的组件,包括表格、面板、窗口、菜单、表单等,这些组件能够帮助开发者构建功能丰富的、响应式的Web应用程序。EXT的核心特性...
它包含一组完整的组件,如表格、面板、菜单、表单等,以及强大的数据绑定和布局管理机制。 - **图书管理系统**: 这个系统主要用于图书的入库、出库、借阅、归还等管理功能,可能还包括图书分类、作者管理、用户借阅...
在"EXT制作的一个酒店系统"中,我们可以推测这个系统是利用EXTJS的组件和功能来实现酒店业务的管理。C# 2.0是.NET Framework的一个版本,它是一种面向对象的编程语言,常用于开发Windows桌面应用、Web应用和服务。在...
描述"里面包含ext的使用文档,和用ext制作的一个案例"表明,压缩包中不仅有ExtJS的官方API文档,还有实际的项目案例。这些文档可以帮助开发者了解每个组件的用法、配置选项以及事件处理,而案例则能够提供实践经验,...
- **跨浏览器兼容性**:能够很好地运行在各种主流浏览器上,包括IE、Chrome、Firefox等。 - **模块化设计**:允许开发者按需加载所需功能,提高应用程序性能。 - **高度可定制**:提供多种样式和主题选择,满足...
10.12 表格与树形的结合——Ext.ux.tree.ColumnTree 第11章 其他布局类简介 11.1 标准布局类 11.1.1 折叠布局——AccordionLayout 11.1.2 边框布局——BorderLayout 11.1.3 卡片式布局——CardLayout 11.1.4 ...
在文件名称列表中,"Ext制作的布局编辑器"可能是一个包含源代码、示例和使用说明的资源包。下载并解压后,开发者可以深入研究布局编辑器的实现细节,学习如何在自己的项目中集成和使用这款工具,或者对其进行二次...
这是一个简单实用的Ext项目,里面涵盖了Ext的树形菜单,Ext与服务器的交互以及服务器返回客户端一个树形菜单的实现,还有Ext可以编辑的表格的制作代码等等,很有用哦!
1. **企业级应用开发**:在开发大型企业管理软件时,使用Ext界面生成器可以快速构建复杂的表格、表单等功能模块。 2. **快速原型制作**:设计师或产品经理可以利用此工具快速制作出产品原型,以便于团队成员之间的...
- **富文本编辑**:除了基本的文字输入,“ext-note”还应支持插入图片、表格、链接等元素,增强笔记的表现力。 - **标签系统**:通过标签对笔记进行分类管理,提高检索效率。 - **版本控制**:保存每次编辑的历史...