欢迎转载,但请保留原帖地址(http://www.liyonghome.cn/index.php/archives/187.html
)
及作者信息(深海区:tacoley@vip.sina.com)
选择这个控件,是因为在昨天进行的一项开发中,需要一个可编辑的GridPanel控件,另外由于科目一项分为3-4级的树形结构,因此就需要
找到一个合适的TreeGridPanel。
在网上查找很久,才发现了在Extjs3.0中,有Ext.ux.maximgb.tg.EditorGridPanel这样一个类提供了对我
需求的支持,初步分析一下,依然有这样一些问题。目前本人还在使用这个控件进行开发,如果有什么新的内容会及时更新,欢迎大家通过E-mail和我共同学
习。至于我的大多数修改都是通过使用来实现,并未修改源代码,其实诸如禁止指定行编辑,非叶子节点进行统计等,都可以通过修改源代码进行封装实现,但是由
于下周就要结束项目开发,时间紧迫,因此没有时间来完善。等项目间歇期有时间了,本人会考虑封装一个新的TreeGrid类来实现以下方法,希望能够和大
家讨论。
1.参数_lft和_rgt不知道如何设置,可不可以不用?
其实_lft和_rgt可以不用设置,网上很多代码提供如下样子的实现
var data = [
{"_id":1,"_parent":null,"_level":1,"_lft":1,"_rgt":98,"_is_leaf":false,"item":" 主营业务成本","YN":64.72},
{"_id":2,"_parent":1,"_level":2,"_lft":2,"_rgt":49,"_is_leaf":true,"item":" 网络维护成本","YN":64.72}
];
var record = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_level', type: 'int'},
{name: '_lft', type: 'int'},
{name: '_rgt', type: 'int'},
{name: '_is_leaf', type: 'bool'},
{name: 'item'},
{name: 'benbu', type: 'float'}
]);
var store = new Ext.ux.maximgb.tg.NestedSetStore({
autoLoad : true,
reader: new Ext.data.JsonReader({id: ‘_id’}, record),
proxy: new Ext.data.MemoryProxy(data)
});
在这里为什么需要设置_lft和_rgt,是因为Ext.ux.maximgb.tg.NestedSetStore的需要,可以通过
TreeGrid.js文件的源代码可以分析,在此Store中,树形结构使用的是基于左右值的无限分类算法。但是在我们的使用当中,去为此json对象
生成此参数却相当的麻烦,至少自己一下没能找到解决的办法。在研究这段的代码的同时,自己也发现了一个同样继承于
Ext.ux.maximgb.tg.AbstractTreeStore的
Ext.ux.maximgb.tg.AdjacencyListStore,最关键的是,这个类所需要的参数,是我们常见的_parent参数,也就是
基于父子关系的树形结构算法。
经过自己测试,可以只需要_parent就可以使用了,如下。
var data = [
{"_id":1,"_parent":null,"_level":1,"_is_leaf":false,"item":"主营业务成本","YN":64.72},
{"_id":2,"_parent":1,"_level":2,"_is_leaf":true,"item":"网络维护成本","YN":64.72}
];
var record = Ext.data.Record.create([
{name: '_id', type: 'int'},
{name: '_level', type: 'int'},
{name: '_is_leaf', type: 'bool'},
{name: 'item'},
{name: 'benbu', type: 'float'}
]);
var store = new Ext.ux.maximgb.tg.AdjacencyListStore({
autoLoad : true,
reader: new Ext.data.JsonReader({id: ‘_id’}, record),
proxy: new Ext.data.MemoryProxy(data)
});
在这里面就没有了_lft和_rgt参数,仅仅更换了一下Store而已。
2.树形结构能不能够默认展开?
通常情况下,大家习惯于在代码的最后调用一个展开方法即可。在源代码中,查到AdjacencyListStore含有一个
expandAll()方法,按照字面意思应该就是展开所有节点的方法。但是在使用当中,却发现没有效果。在expandAll()方法中有这样一个定
义:records = this.data.getRange(),records
应该就是此store中的所有数据的集合,得到以后分别遍历进行展开操作,在调试js的时候发现,得到的这个records.length居然等于0,思
考一会猜测应该是expandAll()比Store的load()方法优先了,在进行展开操作的时候还并未加载到数据。因此自己放弃了Store中的
autoLoad : true这项配置。手工写了load操作和expandAll操作。
store.load();
store.expandAll();
这样调整以后就可以默认展开了,但是当自己将测试的本地数据换成远程的动态调用时,发现又没有效果了,原因是store.load()是异步操作,由
于远程请求较慢,在store.load()操作还并未返回的时候就调用了store.expandAll()操作,这样也就和原来的错误原因一样了。
后来自己将store.expandAll()操作放在了store.load()操作的加载完毕事件里面,才满足了自己的需求,至于是手工的
store.load(),还是autoLoad : true,都无所谓了。
store.on(”load”,function(e){
store.expandAll();
});
3.如何自定义的禁止编辑指定的某一行?
在代码中,我们可以很容易的让某一列不可编辑,因为EditorGridPanel的模型是基于列模型的,在定义列的时候,我们增加了一个
editor属性,去赋值一个编辑器对象,我们不给其赋值就可以实现某一列不可编辑的功能,但是行呢?在api中,似乎没有提供这个功能,看来只有自己去
实现了。首先还是说说我自己的需求:
通过此图来描述我的需求。我的树形结构可能出现3-4级两种,图片所示是3级的情况,我允许编辑的行必须是树中叶子节点的行,比如“大修理”和
“维保”,而非叶子节点及根节点的数据,通过统计所在列的子节点对应数据得到。比如“网络维护成本-本部”,就是由“大修理-本部”和“维保-本部”累加
得到,此处的值不允许编辑。所以得出以下结论:叶子节点所在行可编辑,非叶子节点行不可编辑。(至于统计相关代码在后面讨论,此处仅讨论编辑问题)
因此,我们可以由以下代码实现:
grid.on(”beforeedit”,function(e){
var currRecord = e.record;
if(!currRecord.get(’_is_leaf’)){
e.cancel = true;
}
});
此处是监听grid的beforeedit事件,在edit之前,判断此节点是不是叶子节点,如果不是叶子节点,则取消编辑状态。至于判断是不是叶子
节点,可以通过之前的_is_leaf进行判断(_is_leaf是必须设置的,会影响到树形结构前面的“+”符号图案),另外也可以通过_level进
行判断。
4.如何统计汇总所在列子节点的数值?
在这里,有两种方式进行统计,一种是后台统计好数据,通过json传递给前台Extjs,这种方式不再我们讨论范围,因为这种方式不需要讨论
^_^。我们需要讨论的是,节点没有数据,仅叶子节点含有数据,节点数据是在前台汇总得到的值。
这里对所在列进行统计汇总,首先我就想到了ColumnModel的renderer(渲染)属性,此属性可以配置一个方法,在显示
EditorGridPanel时,调用渲染的方法来实现修改单元格的文字颜色、内容等功能。在这里我也将采用这种方式进行汇总数据。
我给ColumnModel的需要统计的列增加一个renderer:treeNodeSum属性,即在显示此列单元格时,每个单元格会分别调用
treeNodeSum方法。于是我们可以这样实现:
var totalValue;
function treeNodeSum(value, cellmeta, record, rowIndex, columnIndex, store){
if(record.get(’_is_leaf’)){
return value;
}else{
totalValue = 0;
totalNode(record,cellmeta.id);
return totalValue;
}
}
function totalNode(record,fieldName){
if(record.get(’_is_leaf’)){
totalValue += record.get(fieldName);
}
var mixedCollection = store.query(”_parent”,record.get(”_id”));
mixedCollection.each(function(item,index,length){
totalNode(item,fieldName);
});
}
首先是调用treeNodeSum方法,其中判断if(record.get(’_is_leaf’)),当此处为true时,证明此节点是叶
子节点,是被统计项,不需要进行统计,所以直接返回。而非叶子节点,均是统计项,在这里,我写了一个递归函数,去遍历子节点及子节点的字节点等,当子节点
是叶子节点时,将数值进行累加并返回。由此我们就可以在展示的时候汇总当前数据,并显示给用户了,也如之前的图所示,“主营业务成本”和“网络业务成本”
的数字均由前台统计出来的。
到这里,新的问题出来了,页面展示的时候,节点的统计数据出来了,但是当我修改后又怎么更新统计数据呢?将在下一个问题中进行讨论。
5.如何实时更新统计数据?
这里说到,在修改后实时统计,当然马上就联想到在编辑后这个事件下功夫了。首先找到编辑后的事件为:afteredit,
监听这个事件,当发生这个事件时去更新父节点的数据,并递归调用到根节点才结束循环。代码如下:
grid.on(”afteredit”,function(e){
var currValue;
var parentRecord;
var columnName = grid.getColumnModel().getDataIndex(e.column);
var currRecord = e.record;
while(currRecord.get(’_parent’)!==null){
parentRecord = store.getAt(store.find(”_id”,currRecord.get(’_parent’)));
currValue = parentRecord.get(columnName);
currValue -= e.originalValue;
currValue += e.value;
parentRecord.set(columnName,currValue);
parentRecord.dirty = false;
parentRecord.commit();
currRecord = parentRecord;
}
});
这样就可以在修改叶子节点数据后,实时的更新父节点的统计数据。但是这里出现一个情况,当代码去更新父节点的时候,父节点出现了带三角符号的已编辑状
态,在获取store的已修改数据时,会获取到这些数据,这是我们不希望的,因此最好能去除掉统计节点的编辑状态,避免获取修改数据时获取到。
6.如何取消已编辑状态并除去提示的三角符号?
其实在上一节的代码中已经给出了代码,这里进行一下说明,通常步骤分为以下三步:
parentRecord.set(columnName,currValue);
parentRecord.dirty = false;
parentRecord.commit();
首先是修改数据,这个时候页面上会出现三角形的符号提示此字段已被修改。这个时候我们需要设置dirty=false,这样在store获取修改数据
时就不会获得了,但是此刻界面上面没有更新,依然有三角符号的提示,这个时候我们需要commit()一下,就可以消除掉三角符号了。
7.如何一次性批量提交修改了的记录?
var results={};
var recordArray = store.getModifiedRecords();
var recordOld;
for(var i=0;i items = recordArray[i].getChanges();
recordOld = recordArray[i].modified;
for(var key in items){
if( recordOld[key]===”"){
results["item("+key+"#"+recordArray[i].get(”_id”)+”#Insert)”]=items[key];
}else{
results["item("+key+"#"+recordArray[i].get(”_id”)+”#Update)”]=items[key];
}
}
}
在这段代码里面,我们首先获取了已修改了的Record记录数组,之后再遍历这个数组,分别获得每一个修改了的具体字段,再通过判断原始值是不是
为”"(在这里突然想到,如果没有值的话,.modified会不会是null?等有时间了测试一下),当为空代表是新增的数据,否则是修改的数据。通过
这种方式,我们最终得到的resules对象,可以作为一个json对象通过Ajax的params属性直接赋值传递。
resules对象的json字符串例如:[{"item(YN#8888#Insert)":999},
{"item(YN#9999#Update)":888}]。
由于本人是使用java struts进行编程,因此后台可以用名叫item的Map进行获取(如何获取不明白的可以搜索下Map-Backed
ActionForm的实现方式)。获得的Map的键值分别为:
YN#8888#Insert(键):999(值)
YN#9999#Update(键)::888(值)
这样的话我们就可以分析键来实现具体的业务了。
8.如何实时的分别提交修改了的记录?
此功能并未在我的代码里面使用,主要考虑到在用户的编辑过程当中一直不停的操作数据库不太好,但是如果数据较少的朋友也可以尝试此方式。可以通
过注册afteredit事件实现。
grid.on(”afteredit”,function(e){
});
在此方法中传入的e参数实际上是一个Event,包含了此数据的值信息,行列值等,通过这些数据就可以得到此数据的归属,之后发起一个异步的Ajax
请求。这里最好还是做一下失败判断,如果有保存失败的提示用户,并且将修改了的值还原最好。当修改成功以后,清除修改提示状态。
分享到:
相关推荐
在EXTJS框架中,`Ext.ux.form.LovCombo`是一种自定义组件,它扩展了基本的`Ext.form.field.ComboBox`,提供了更丰富的功能,尤其是针对多选和联动选择的需求。这个组件通常用于创建具有“lov”(即“Look Up Value”...
在ExtJS框架中,`Ext.ux.tree.TreeGrid`组件是一种结合了树形结构与表格显示特性的控件,适用于展示具有层级关系的数据。通过这种组件,用户可以在一个界面上同时查看数据的层次结构以及具体数据内容。 #### 二、...
这个"Ext.ux.UploadDialog.zip"压缩包包含了EXTjs的UploadDialog组件,方便开发者在自己的项目中直接使用。 UploadDialog组件的核心功能是提供一个用户友好的界面,让用户能够选择并上传文件到服务器。这个组件通常...
### ExtJs选中 `var ...以上就是关于 `var editor = new Ext.ux.grid.RowEditor` 的详细解析,希望对使用ExtJs框架的开发者有所帮助。通过合理地配置和使用 `RowEditor`,可以极大地提高Web应用的交互性和用户体验。
在实际使用`Ext.ux.SwfUploadPanel.js`时,你需要在ExtJS应用程序中引入这个文件,并配置相关参数,例如服务器端处理脚本地址、允许的文件类型、最大文件大小等。然后,你可以像创建其他ExtJS组件一样,实例化...
1、Ext.ux.aceeditor.Panel 2、Ext.ux.grid.feature.Tileview 3、Ext.ux.upload.Button 4、Ext.ux.toggleslide.ToggleSlide 5、Ext.ux.container.ButtonSegment 6、Ext.ux.grid.plugin.RowEditing 7、Ext.ux.grid....
Most configuration options are inherited from Ext.Window (see ExtJs docs). The added ones are: url - the url where to post uploaded files. base_params - additional post params (default to {}). ...
extjs3.0 ext3.0 ext文档 ext例子
Ext.ux.UploadDialog批量上传文件实例是一个基于ExtJS组件库扩展插件的文件上传解决方案,主要针对需要一次性处理多个文件上传的应用场景。ExtJS是一个强大的JavaScript框架,它提供了丰富的用户界面组件,而Ext.ux....
绝对的ExtJS3.0中文API,本人在网上找了好久才找到的,在此奉献给大家!!解压后有30多兆!!
在ExtJS 4.x框架中,ComboboxTree是一种特殊的组件,它将传统的下拉框与树形结构结合在一起,提供了一种更为灵活的用户输入方式。这种组件在数据选择上非常实用,尤其当数据层级关系复杂时,可以方便地进行多选或...
在EXTJS这个强大的JavaScript框架中,`Ext.Panel`和`TreePanel`是两个非常重要的组件,它们被广泛用于构建复杂的用户界面。这篇文章将探讨如何在这些组件中动态加载本地页面数据,以提升用户体验并实现灵活的数据...
在Ext JS中,“Notification”插件是用于显示通知消息的一个组件,它可以帮助开发者在用户界面上创建吸引人且易于理解的提示信息。本文将深入探讨Ext JS Notification插件的使用方法、功能特性以及如何集成到项目中...
首先,Ext.ux.UploadDialog是一个基于ExtJS框架的组件,它允许用户在一个对话框中选择并上传多个文件。这个组件通常包含一个文件选择输入框、上传按钮、进度条和取消上传的功能。它的主要优势在于能够提供友好的用户...
### ExtDesigner for extjs3.0 使用帮助文档 #### Introduction ExtJs3.0是一款卓越的JavaScript框架,它以其强大的功能、丰富的组件库以及对JSON数据格式的支持而著称。尽管如此,对于开发者来说,掌握所有组件的...
【Ext 3.x + Ext 2.x 下拉树 Ext.ux.ComboBoxTree】是基于ExtJS框架的一个组件,它结合了下拉框(ComboBox)和树形控件(TreePanel)的功能,提供了一种用户友好的选择界面。在网页应用中,这种控件常用于展示层级...
Ext.ux.UploadDialog 是一个 ExtJS 框架的扩展组件,它提供了一个友好的用户界面来处理文件上传。在服务器端,我们需要正确解析接收到的请求,以便能够读取并处理上传的文件。在 Java 环境下,Apache Commons ...
在3.4.0版本中,`ext.jsb2` 文件是一个关键组成部分,它对于理解和开发基于ExtJS的应用程序至关重要。这个文件的缺失可能会对升级到4.0.0版本的开发者造成困扰,因为4.0.0版本不再包含这个文件,但幸运的是,它可以...
extJS3.0 extJS3.0 extJS3.0 extJS3.0 extJS3.0 extJS3.0 extJS3.0
《Packtpub.Ext.JS.3.0.Cookbook.Oct.2009》是一部专注于Ext JS 3.0框架的实战指南,由Packtpub出版社于2009年10月出版。这本书旨在帮助开发者充分利用Ext JS 3.0的功能,构建高效、美观的Web应用程序。Ext JS是一个...