`
babydeed
  • 浏览: 238277 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于Extjs3.0中的TreeGrid (Ext.ux.maximgb.tg.EditorGridPanel)(转)

    博客分类:
  • Ext
阅读更多

转:(http://www.liyonghome.cn/index.php/archives/187.html )

 

  选择这个控件,是因为在昨天进行的一项开发中,需要一个可编辑的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 请求。这里最好还是做一下失败判断,如果有保存失败的提示用户,并且将修改了的值还原最好。当修改成功以后,清除修改提示状态。

  • 大小: 9.4 KB
分享到:
评论
2 楼 忘了名字亻 2011-08-30  
楼主  有没有试异步加载子结点  如果子结点过多加载的时候页面就卡死在那了 该如何解决
1 楼 silvernet 2010-11-12  
用官方自带的杯具了,不能编辑,后来换成楼主说的,就好了,多谢分享!

相关推荐

    extjs-Ext.ux.form.LovCombo下拉框

    在EXTJS框架中,`Ext.ux.form.LovCombo`是一种自定义组件,它扩展了基本的`Ext.form.field.ComboBox`,提供了更丰富的功能,尤其是针对多选和联动选择的需求。这个组件通常用于创建具有“lov”(即“Look Up Value”...

    Ext.ux.tree.treegrid异步加载

    在ExtJS框架中,`Ext.ux.tree.TreeGrid`组件是一种结合了树形结构与表格显示特性的控件,适用于展示具有层级关系的数据。通过这种组件,用户可以在一个界面上同时查看数据的层次结构以及具体数据内容。 #### 二、...

    Ext.ux.UploadDialog.zip

    这个"Ext.ux.UploadDialog.zip"压缩包包含了EXTjs的UploadDialog组件,方便开发者在自己的项目中直接使用。 UploadDialog组件的核心功能是提供一个用户友好的界面,让用户能够选择并上传文件到服务器。这个组件通常...

    ExtJs选中var editor = new Ext.ux.grid.RowEditor详解

    ### ExtJs选中 `var ...以上就是关于 `var editor = new Ext.ux.grid.RowEditor` 的详细解析,希望对使用ExtJs框架的开发者有所帮助。通过合理地配置和使用 `RowEditor`,可以极大地提高Web应用的交互性和用户体验。

    Ext.ux.SwfUploadPanel.js

    在实际使用`Ext.ux.SwfUploadPanel.js`时,你需要在ExtJS应用程序中引入这个文件,并配置相关参数,例如服务器端处理脚本地址、允许的文件类型、最大文件大小等。然后,你可以像创建其他ExtJS组件一样,实例化...

    extjs4.1-ux.rar

    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....

    Ext.ux.UploadDialog

    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文档 ex例子

    extjs3.0 ext3.0 ext文档 ext例子

    Ext.ux.UploadDialog批量上传文件实例

    Ext.ux.UploadDialog批量上传文件实例是一个基于ExtJS组件库扩展插件的文件上传解决方案,主要针对需要一次性处理多个文件上传的应用场景。ExtJS是一个强大的JavaScript框架,它提供了丰富的用户界面组件,而Ext.ux....

    ExtJS3.0中文API

    绝对的ExtJS3.0中文API,本人在网上找了好久才找到的,在此奉献给大家!!解压后有30多兆!!

    Extjs4.X下comboboxTree下拉树型菜单,完美支持多选、单选,绝对好用

    在ExtJS 4.x框架中,ComboboxTree是一种特殊的组件,它将传统的下拉框与树形结构结合在一起,提供了一种更为灵活的用户输入方式。这种组件在数据选择上非常实用,尤其当数据层级关系复杂时,可以方便地进行多选或...

    Ext JS Notification 插件

    在Ext JS中,“Notification”插件是用于显示通知消息的一个组件,它可以帮助开发者在用户界面上创建吸引人且易于理解的提示信息。本文将深入探讨Ext JS Notification插件的使用方法、功能特性以及如何集成到项目中...

    ext 多文件上传控件 Ext.ux.UploadDialog 使用中的问题

    首先,Ext.ux.UploadDialog是一个基于ExtJS框架的组件,它允许用户在一个对话框中选择并上传多个文件。这个组件通常包含一个文件选择输入框、上传按钮、进度条和取消上传的功能。它的主要优势在于能够提供友好的用户...

    extjs中Ext.Panel和TreePanel 组件动态加载本地页面数据

    在EXTJS这个强大的JavaScript框架中,`Ext.Panel`和`TreePanel`是两个非常重要的组件,它们被广泛用于构建复杂的用户界面。这篇文章将探讨如何在这些组件中动态加载本地页面数据,以提升用户体验并实现灵活的数据...

    ExtDesigner for extjs3.0使用帮助文档.pdf

    ### ExtDesigner for extjs3.0 使用帮助文档 #### Introduction ExtJs3.0是一款卓越的JavaScript框架,它以其强大的功能、丰富的组件库以及对JSON数据格式的支持而著称。尽管如此,对于开发者来说,掌握所有组件的...

    [Ext 3.x + Ext 2.x] 下拉树 Ext.ux.ComboBoxTree

    【Ext 3.x + Ext 2.x 下拉树 Ext.ux.ComboBoxTree】是基于ExtJS框架的一个组件,它结合了下拉框(ComboBox)和树形控件(TreePanel)的功能,提供了一种用户友好的选择界面。在网页应用中,这种控件常用于展示层级...

    如何在服务器端 读取Ext.ux.UploadDialog上传的文件?

    Ext.ux.UploadDialog 是一个 ExtJS 框架的扩展组件,它提供了一个友好的用户界面来处理文件上传。在服务器端,我们需要正确解析接收到的请求,以便能够读取并处理上传的文件。在 Java 环境下,Apache Commons ...

    ExtJS 3.4.0中的 ext.jsb2 文件

    在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 extJS3.0

    Packtpub.Ext.JS.3.0.Cookbook.Oct.2009

    《Packtpub.Ext.JS.3.0.Cookbook.Oct.2009》是一部专注于Ext JS 3.0框架的实战指南,由Packtpub出版社于2009年10月出版。这本书旨在帮助开发者充分利用Ext JS 3.0的功能,构建高效、美观的Web应用程序。Ext JS是一个...

Global site tag (gtag.js) - Google Analytics