`

Extjs3.0中的TreeGrid

阅读更多

 

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< recordArray.length;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请求。这里最好还是做一下失败判断,如果有保存失败的提示用户,并且将修改了的值还原最好。当修改成功以后,清除修改提示状态

 

 

 

 

 

 

 

  • 大小: 32 KB
分享到:
评论

相关推荐

    ExtJS3.0中文API

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

    extJS3.0完整包

    extJS3.0 extJS3.0 extJS3.0 extJS3.0 extJS3.0 extJS3.0 extJS3.0

    Extjs3.0 中文API帮助文档

    Extjs3.0中文API文档 够详细 够详细 够详细

    ExtJS3.0 源码分析与开发实例宝典

    ExtJS3.0 源码分析与开发实例宝典

    EXTJS3.0中文API (离线)

    EXTJS 3.0是该框架的一个重要版本,它提供了一系列先进的组件和功能,帮助开发者创建功能强大的Web应用。中文API手册是EXTJS开发者的重要参考资料,它使得不懂英语或者英语水平有限的开发者也能方便地学习和使用...

    extjs3.0 中扩展的日期控件

    由于extjs3.0自己封装的时间不能够选择时分秒,给大家开发带来了一些麻烦。虽然网上有ext2.0的日期扩展控件,但在3.0中不能用。公司现在项目正用了,因此我就对extjs3.0时间控件的扩展,实现了可选择时分秒功能。...

    extjs3.0开发包含示例api

    EXTJS 3.0是一款基于JavaScript的开源UI框架,它为Web应用提供了丰富的组件和功能。这个开发包包含了EXTJS 3.0的核心API、示例代码和源文件,是学习和开发EXTJS应用程序的重要资源。 一、EXTJS 3.0 API EXTJS 3.0的...

    Extjs3.0 常用组件介绍及怎么安装开发利器Spket

    以下是一些ExtJS 3.0中的常用组件: 1. **Panel(面板)**: Panel是最基本的容器,可以包含其他组件,常用于构建复杂的布局。它支持标题、工具栏、滚动条等特性。 2. **Grid(网格)**: Grid组件用于展示表格数据...

    EXTJS3.0登陆DEMO

    在EXTJS3.0登录DEMO中,STRUTS2可能是负责接收前端发送的登录请求,验证用户凭据,并返回登录结果的框架。 SPRING作为企业级Java的全栈框架,提供了依赖注入、AOP(面向切面编程)、事务管理等功能。在登录场景中,...

    ExtJs3.0 中文破解视图编辑器.rar

    ExtJs3.0 中文破解视图编辑器.rar AIR安装程序 Ext 帮组文档 你的支持就是我上传的动力 资源共享

    extjs3.0 组件

    在这个课程中,我们将深入探讨EXTJS 3.0 的核心组件,这些组件是构建用户界面的基础。 首先,我们要了解EXTJS 3.0 的基础——面板(Panel)。面板是EXTJS 中最常用的组件,它可以包含其他组件,如表格、表单、按钮...

    extjs3.0中英文对照chm api

    extjs3.0中英文对照chm api

    Extjs 3.0 中文API

    Extjs 3.0 中文API Extjs 3.0 中文API

    extjs3.0中文API

    在ExtJS 3.0中,核心知识点包括: 1. **组件系统**:ExtJS 3.0包含了大量的UI组件,如按钮(Button)、表格(Grid)、面板(Panel)、表单(Form)等,这些组件可以通过配置项灵活定制,以满足各种需求。 2. **...

    EXTJS3.0多文件上传组件

    在"EXTJS3.0多文件上传组件"中,我们主要关注的是如何利用EXTJS3.0的功能来实现一个高效的、用户友好的多文件上传功能。 首先,`swfupload.js`是Flash-Based的文件上传库,它允许用户在不离开当前页面的情况下进行...

    extjs3.0 API 中英

    在ExtJS 3.0的API中,我们可以找到以下几个重要的知识点: 1. **组件系统**:ExtJS的核心是它的组件模型,包括各种类型的控件如表格(Grid)、面板(Panel)、窗口(Window)、菜单(Menu)等。这些组件可以组合成...

    ExtJs3.0中文帮助文档(chm格式)

    "ExtJs3.0中文帮助文档(chm格式)"是针对开发者的重要参考资料,提供了详尽的API文档和教程,帮助开发者更好地理解和使用ExtJS 3.0框架。 该CHM( Compiled HTML Help)格式的文档包含了以下关键知识点: 1. **组件...

    Extjs3.0中文文档大全

    "Extjs3.0中文文档大全"提供了全面的指南,帮助开发者深入理解和有效地利用这个版本的ExtJS。 文档可能包括以下几个关键部分: 1. **快速入门**:这部分通常会介绍如何在项目中引入ExtJS库,创建基本的页面结构,...

    ExtJS 3.0 API 文档离线包

    3. **数据绑定**:3.0版本中,ExtJS引入了Model(模型)和Store(存储)的概念,使得数据与视图之间的绑定更加直观和强大。这极大地简化了数据操作和更新界面的工作。 4. **Ajax与数据通信**:Ext.Ajax模块提供了...

Global site tag (gtag.js) - Google Analytics