DojoX DataGrid

来源:互联网 发布:2017网络热曲 编辑:程序博客网 时间:2024/06/10 02:17

Grid 可能是 DojoX 中最受欢迎的部件,比起普通的 Web 表格部件,Grid 更像一个基于 Web 的 Excel 组件。这使得 Grid 足可以应付较为复杂的数据展示及数据操作。在 dojox1.2 中,dojox.grid 包中新增了 DataGrid 类,该类是对原 Grid 类的强化和替代,之所以叫做 DataGrid,是由于该类与 dojo 的数据操作类 store 无缝整合在一起。而之前的 Grid 需要将 store 对象包装为 model 对象才能使用。

我们为什么需要 Grid 呢?下面列出了 Grid 的特性:

  • 用户只需向下拖动滚动条,Grid 即可加载延迟的记录,省去了翻页操作,减少 Web 与服务器交互,提高了性能;
  • 可以任意的增加和删除单元格、行、或者列;
  • 对行进行统计摘要,Grid 可以生成类似于 OLAP 分析的报表;
  • Grid 超越了二维表格的功能,它可以跨行或跨列合并单元格以满足不同的数据填充的需求;
  • 行列冻结功能,使得浏览数据更加灵活方便;
  • Grid 事件采用了钩子机制,我们可以通过 onStyle 钩子完成对样式的更改;
  • 单元格具备富操作,所有的 dijit 部件都可以在单元格中使用,并且单元格可以通过单击转换为编辑状态;
  • 可以为不同的单元格设置不同的上下文菜单;
  • Grid 嵌套,也就是说 Grid 可以在单元格中嵌套其他的 Grid,从而组成更为复杂的应用;

除此之外,Grid 还有具有其他很多特性,例如,非常实用的偶数行上色、灵活的选取功能、自动调整列宽、数据的展开 / 合闭等。

DataGrid 基础

要创建一个 DojoX DataGrid,就需要对 DataGrid 的基本工作过程有一个大致的了解。一个 DataGrid 实例的组成结构如下图所示,DojoX DataGrid 是使用 DataGrid 的基础,因此在使用 Grid 的时候需要加载相关的 dojox 包;一个小部件通常由框架和样式组成,因此,我们需要指定 DataGrid 的样式表并且声明 DataGrid 实例。DataGrid 实例会组合一个 Structure 和一个 Store。Structure 是一个表头及数据模型的定义,而 Store 用于承载数据。

清单 2. 定义布局
 var layout = [  {field: 'pro_no', name: 'Product Number' },  {field: 'pro', name: 'Product' },  {field: 'min_amount', name: 'Minimum Amount' },  {field: 'max_amount', name: 'Maximum Amount' },  {field: 'avg_amount', name: 'Average Amount' }  ];

这里定义了一个数组 layout,其中每一个成员表示一个列的定义,其中 field 指定了使用的数据项,该取值需要遵循 javascript 变量定义规则;name 为该列显示的名称。接下来是 store 的开发,代码如清单 3

清单 3. 开发 store
 var sampleData = {  identifier: 'pro_no',  label: 'pro_no',  items: [  {pro_no:'2100', pro:'A Series', min_amount:346, max_amount:931, avg_amount:647},  {pro_no:'2200', pro:'B Series', min_amount:301, max_amount:894, avg_amount:608},  {pro_no:'2300', pro:'C Series', min_amount:456, max_amount:791, avg_amount:532},  {pro_no:'2400', pro:'D Series', min_amount:859, max_amount:2433, avg_amount:1840},  {pro_no:'2500', pro:'E Series', min_amount:459, max_amount:1433, avg_amount:1040}  ]  };  var jsonStore = new dojo.data.ItemFileReadStore({ data: sampleData });

在这里,我们首先定义一个 JSON 数据 sampleData,这里 identifier 是对于整行的唯一标识,因此在数据中不能出现重复;数组 items 是这个表格所显示的数据,其中数据必须完全符合 JSON 的语法,字符串两端必须使用引号,否则会出现语法错误,保险的办法是所有的值均用引号括住。

接下来,我们就要在网页的 Body 元素中定义 DataGrid 实例了,如 清单 4

清单 4. 定义 DataGrid 实例
 <div id="grid" dojoType="dojox.grid.DataGrid" store="jsonStore" structure="layout" autoWidth="true" ></div>

dojoType 指定了该 Web 部件为 dojox.grid.DataGrid,数据使用 jsonStore,结构为 layout,自动调整宽度。到此,第一个 Grid 就已开发完毕,完整代码如清单 5

<html>  <head>  <title>first Grid</title>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>  <link rel="stylesheet" href="dojox/grid/resources/tundraGrid.css" media="screen"> <link rel="stylesheet" href="dojo/resources/dojo.css" media="screen">  <script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true"></script>  <script type="text/javascript">  dojo.require("dojo.data.ItemFileReadStore");  dojo.require("dojox.grid.DataGrid");  var sampleData = { identifier: 'pro_no', label: 'pro_no',  items: [  {pro_no:'2100', pro:'A Series', min_amount:346, max_amount:931, avg_amount:647},  {pro_no:'2200', pro:'B Series', min_amount:301, max_amount:894, avg_amount:608},  {pro_no:'2300', pro:'C Series', min_amount:456, max_amount:791, avg_amount:532},  {pro_no:'2400', pro:'D Series', min_amount:859, max_amount:2433, avg_amount:1840},  {pro_no:'2500', pro:'E Series', min_amount:459, max_amount:1433, avg_amount:1040}  ] };  var jsonStore = new dojo.data.ItemFileReadStore({ data: sampleData });  var layout = [  {field: 'pro_no', name: 'Product Number' },  {field: 'pro', name: 'Product' },  {field: 'min_amount', name: 'Minimum Amount' },  {field: 'max_amount', name: 'Maximum Amount' },  {field: 'avg_amount', name: 'Average Amount' }];  </script>  </head>  <body class="tundra">  <div class="heading">First Grid</div>  <div id="grid" dojoType="dojox.grid.DataGrid" store="jsonStore" structure="layout" autoWidth="true"></div>  </body>  </html>

DataGrid 开发详解

DataGrid 的创建

在 DataGrid 的开发中,有三种方法创建 DataGrid 实例,第一种是 javascript 创建结构,html 代码创建实例,我们第一个例子就是使用这种方式实现的;

第二种是由 html 代码创建结构及实例,在这种方法中,我们使用 table 标签,定义 Grid 的结构,而省去了在 javascript 中定义 structure 的部分。具体定义方式与标准的 html 书写方式非常类似,定义方式如清单 6

清单 6. 由 html 代码创建结构及实例
 <table id="gridNode" jsid="grid" dojoType="dojox.grid.DataGrid" store="jsonStore" rowsPerPage="20" region="center">  <thead>    <tr>      <th field="pro_no" >Product Number</th>      <th field="pro" >Product</th>      <th field="min_amount" >Minimum Amount</th>      <th field="max_amount" >Maximum Amount</th>      <th field="avg_amount" >Average Amount</th>    </tr>  </thead>  </table>
<html>  <head>  <title>Table Grid</title>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>  <link rel="stylesheet" href="dojox/grid/resources/tundraGrid.css" media="screen"> <link rel="stylesheet" href="dojo/resources/dojo.css" media="screen">  <script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true"></script>  <script type="text/javascript">  dojo.require("dojo.data.ItemFileReadStore");  dojo.require("dojox.grid.DataGrid");  var sampleData = { identifier: 'pro_no', label: 'pro_no',  items: [  {pro_no:'2100', pro:'A Series', min_amount:346, max_amount:931, avg_amount:647},  {pro_no:'2200', pro:'B Series', min_amount:301, max_amount:894, avg_amount:608},  {pro_no:'2300', pro:'C Series', min_amount:456, max_amount:791, avg_amount:532},  {pro_no:'2400', pro:'D Series', min_amount:859, max_amount:2433, avg_amount:1840},  {pro_no:'2500', pro:'E Series', min_amount:459, max_amount:1433, avg_amount:1040}  ] };  var jsonStore = new dojo.data.ItemFileReadStore({ data: sampleData });   </script>  </head>  <body class="tundra"> <div class="heading">Table Grid</div> <table id="gridNode" jsid="grid" dojoType="dojox.grid.DataGrid"store="jsonStore" rowsPerPage="20" region="center">  <thead>    <tr>  <th field="pro_no" >Product Number</th>  <th field="pro" >Product</th>  <th field="min_amount" >Minimum Amount</th>  <th field="max_amount" >Maximum Amount</th>  <th field="avg_amount" >Average Amount</th>    </tr>  </thead>  </table> </body>  </html>

第三种方式就是采用纯 javascript 的方式定义 DataGrid 实例,清单 7声明网页加载完成后就在 id 为 gridNode 的页面结点上创建一个 DataGrid 实例。

清单 7. 纯 javascript 的方式定义 DataGrid 实例
 dojo.addOnLoad(function(){  // 指定页面加载完毕后执行 var grid = new dojox.grid.DataGrid({  query: { pro_no: '*' },  id: 'grid2',  store: jsonStore,  structure: [  {field: 'pro_no', name: 'Product Number' },  {field: 'pro', name: 'Product' },  {field: 'min_amount', name: 'Minimum Amount' },  {field: 'max_amount', name: 'Maximum Amount' },  {field: 'avg_amount', name: 'Average Amount' }  ],rowsPerPage: 20   }, 'gridNode');  // 设置 grid 显示在 id 为 gridNode 的节点下 grid.startup();  // 启动 grid  });

Grid1.2 可以通过这种方式很方便的与 dojo 容器结合在一起,动态创建页面布局。

<html>  <head>  <title>Javascript Grid</title>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>  <link rel="stylesheet" href="dojox/grid/resources/tundraGrid.css" media="screen"> <link rel="stylesheet" href="dojo/resources/dojo.css" media="screen">  <script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true"></script>  <script type="text/javascript">  dojo.require("dojo.data.ItemFileReadStore");  dojo.require("dojox.grid.DataGrid");  var sampleData = { identifier: 'pro_no', label: 'pro_no',  items: [  {pro_no:'2100', pro:'A Series', min_amount:346, max_amount:931, avg_amount:647},  {pro_no:'2200', pro:'B Series', min_amount:301, max_amount:894, avg_amount:608},  {pro_no:'2300', pro:'C Series', min_amount:456, max_amount:791, avg_amount:532},  {pro_no:'2400', pro:'D Series', min_amount:859, max_amount:2433, avg_amount:1840},  {pro_no:'2500', pro:'E Series', min_amount:459, max_amount:1433, avg_amount:1040} ] };  var jsonStore = new dojo.data.ItemFileReadStore({ data: sampleData });  dojo.addOnLoad(function(){  // 指定页面加载完毕后执行 var grid = new dojox.grid.DataGrid({  query: { pro_no: '*' },  id: 'grid2',  store: jsonStore,  structure: [  {field: 'pro_no', name: 'Product Number' },  {field: 'pro', name: 'Product' },  {field: 'min_amount', name: 'Minimum Amount' },  {field: 'max_amount', name: 'Maximum Amount' },  {field: 'avg_amount', name: 'Average Amount' } ],rowsPerPage: 20  }, 'gridNode');  // 设置 grid 显示在 id 为 gridNode 的节点下 grid.startup();  // 启动 grid  }); </script>  </head>  <body class="tundra"> <div class="heading">Javascript Grid</div> <div id="gridNode"></div> </body>  </html>

Structure 详解

DataGrid 不仅可以创建简单的二维表格,还可以通过对 structure 的设计创建复杂的表格应用,同时还可以为每一列进行格式化或是取值。我们将 First Grid 进行简单的修改,得到清单 8的代码。

清单 8. 修改 First Grid
 function formatAmount(value){  return '$ ' + value;  }  function getRange(rowIndex, item){  if(!item){return '--';}  var grid = dijit.byId('grid');  var max = grid.store.getValue(item, "max_amount");  var min = grid.store.getValue(item, "min_amount");  return max - min;  }  var subrow1 = [  {field: 'pro_no', name: 'Product Number', rowSpan: 2 },  {field: 'pro', name: 'Product', rowSpan: 2 },  {field: 'min_amount', name: 'Min. Amount',formatter: formatAmount,width: '80px' },  {field: 'avg_amount', name: 'Average Amount',formatter: formatAmount, rowSpan: 2 },  {field: 'range', name: 'Range',get:getRange, rowSpan: 2 }  ];  var subrow2 = [  {field: 'max_amount', name: 'Max. Amount',formatter: formatAmount},  ];  var layout = [subrow1,subrow2];

这里,我们从新定义了 layout,将 layout 分为两个子行,其中子行 1 包含了五个字段,其中 pro_no、pro、avg_amount、range 具有值为 2 的 rowSpan 属性,也就表明这三列跨越了两行。第二行仅有 max_amount 一个字段。同时,我们为三个 amount 字段指定了 formatter 函数,在其数值前添加美元符号。为 range 字段指定了 get 方法来自动获取最大值与最小值的差。

<html> <head> <title>RowSpan Grid</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> <link rel="stylesheet" href="dojox/grid/resources/tundraGrid.css" media="screen"> <link rel="stylesheet" href="dojo/resources/dojo.css" media="screen">  <script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true"></script> <script type="text/javascript">     dojo.require("dojo.data.ItemFileReadStore");     dojo.require("dojox.grid.DataGrid");     var sampleData = {         identifier: 'pro_no',         label: 'pro_no',         items: [             {pro_no:'2100', pro:'A Series', min_amount:346, max_amount:931, avg_amount:647},             {pro_no:'2200', pro:'B Series', min_amount:301, max_amount:894, avg_amount:608},             {pro_no:'2300', pro:'C Series', min_amount:456, max_amount:791, avg_amount:532},             {pro_no:'2400', pro:'D Series', min_amount:859, max_amount:2433, avg_amount:1840},             {pro_no:'2500', pro:'E Series', min_amount:459, max_amount:1433, avg_amount:1040}         ]     };     var jsonStore = new dojo.data.ItemFileReadStore({ data: sampleData });         function formatAmount(value){         return '$ ' + value;     }     function getRange(rowIndex, item){         if(!item){return '--';}         var grid = dijit.byId('grid');         var max = grid.store.getValue(item, "max_amount");         var min = grid.store.getValue(item, "min_amount");         return max - min;     }     var subrow1 = [         {field: 'pro_no', name: 'Product Number', rowSpan: 2 },         {field: 'pro', name: 'Product', rowSpan: 2 },         {field: 'min_amount', name: 'Min. Amount',formatter: formatAmount,width: '80px' },         {field: 'avg_amount', name: 'Average Amount',formatter: formatAmount, rowSpan: 2 },         {field: 'range', name: 'Range',get:getRange, rowSpan: 2 }     ];     var subrow2 = [         {field: 'max_amount', name: 'Max. Amount',formatter: formatAmount},     ];     var layout = [subrow1,subrow2]; </script> </head> <body class="tundra"> <div class="heading">RowSpan Grid</div> <div id="grid" dojoType="dojox.grid.DataGrid" store="jsonStore" structure="layout" autoWidth="true" style="height:500px;"></div> </body> </html>

除了 rowSpan 属性外我们还可以使用 colSpan 属性,这两个属性的用法与 html 中的用法一致,并且可以在 html 定义表结构中使用,我们再看这个表头的例子来理解一下 colSpan 的用法。

<html>  <head>  <title>ColSpan Grid</title>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>  <link rel="stylesheet" href="dojox/grid/resources/tundraGrid.css" media="screen"> <link rel="stylesheet" href="dojo/resources/dojo.css" media="screen">  <script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true"></script>  <script type="text/javascript">  dojo.require("dojo.data.ItemFileReadStore");  dojo.require("dojox.grid.DataGrid");  var sampleData = { identifier: 'pro_no', label: 'pro_no',  items: [  {pro_no:'2100', pro:'A Series', min_amount:346, max_amount:931, avg_amount:647},  {pro_no:'2200', pro:'B Series', min_amount:301, max_amount:894, avg_amount:608},  {pro_no:'2300', pro:'C Series', min_amount:456, max_amount:791, avg_amount:532},  {pro_no:'2400', pro:'D Series', min_amount:859, max_amount:2433, avg_amount:1840},  {pro_no:'2500', pro:'E Series', min_amount:459, max_amount:1433, avg_amount:1040}  ] };  var jsonStore = new dojo.data.ItemFileReadStore({ data: sampleData });  function formatAmount(value){  return '$ ' + value;  } var structure = [[  {field: 'pro_no', name: 'pro_no', rowSpan: 2},  {field: 'pro', name: 'Product', rowSpan: 2},  {field: 'min_amount', name: 'min_amount',formatter: formatAmount },  {field: 'max_amount', name: 'max_amount',formatter: formatAmount }  ],[  {field: 'avg_amount', name: 'avg_amount',formatter: formatAmount, colSpan: 2 }  ]]; </script>  </head>  <body class="tundra">  <div class="heading">ColSpan Grid</div>  <div id="grid" dojoType="dojox.grid.DataGrid" store="jsonStore" structure="structure" autoWidth="true" style="height:500px;"></div>  </body>  </html>

Store 的使用

DataGrid 使用了 Store 作为数据源,在以上的例子中,我们都是将数据写在 javascript 中然后作为 data 参数值传给 Store 的构造方法。但是在大多数情况下,数据是要动态的通过 Ajax 请求从服务器端获取的,这同样可以通过 Store 来实现。我们仅需要将声明 Store 对象时传入请求的 url 地址即可,如:new dojo.data.ItemFileReadStore({url: 'jsondata.txt' }) 。Store 包括 dojo.data.ItemFileReadStore 和 dojo.data.ItemFileWriteStore 两个类。我们在使用 DataGrid 的编辑功能时需要使用 ItemFileWriteStore 来作为数据源。下面就演示了一个多功能的 DataGrid,这个 Grid 使用外部数据源,可以对单元格进行编辑,并且可以通过右击表头弹出列选菜单

dataGrid.txt

{  identifier: 'emp_no',  label: 'emp_no',  items: [  {emp_no:'2100', name:'Matt', gender:'M', dept_no:730, bonus:647},  {emp_no:'2200', name:'Lisa', gender:'F', dept_no:731, bonus:608},  {emp_no:'2300', name:'Mick', gender:'M', dept_no:732, bonus:532},  {emp_no:'2400', name:'John', gender:'M', dept_no:733, bonus:1840},  {emp_no:'2500', name:'Jan', gender:'M', dept_no:734, bonus:1040},  {emp_no:'2101', name:'Jeff', gender:'M', dept_no:730, bonus:647},  {emp_no:'2202', name:'Frank', gender:'M', dept_no:731, bonus:608},  {emp_no:'2303', name:'Fred', gender:'M', dept_no:732, bonus:532} ] }

html代码:

<html>  <head>  <title>Ajax Data Grid</title>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>  <link rel="stylesheet" href="dojox/grid/resources/tundraGrid.css" media="screen"> <link rel="stylesheet" href="dijit/themes/tundra/tundra.css" media="screen"> <link rel="stylesheet" href="dojo/resources/dojo.css" media="screen">  <script type="text/javascript" src="dojo/dojo.js" djConfig="parseOnLoad: true"></script>  <script type="text/javascript">  dojo.require("dojo.data.ItemFileWriteStore");  dojo.require("dojox.grid.DataGrid");  // 下面两个包用来创建右键弹出菜单 dojo.require("dijit.Menu");  dojo.require("dojox.widget.PlaceholderMenuItem");    // 使用 dataGrid.txt 中的数据作为填充 DataGrid 的数据 var jsonStore = new dojo.data.ItemFileWriteStore({ url:'dataGrid.txt'});  var layout = [  {field: 'emp_no', name: 'Employee Number',width:"100px"},  {field: 'name', name: 'Name', editable: true ,width:"100px"},  // 该列可编辑,双击鼠标 {field: 'gender', name: 'Gender', editable:true, type:dojox.grid.cells.Select, options:['F','M'],width:"100px"}, // 编辑该列时使用下拉菜单,双击鼠标 {field: 'dept_no', name: 'Deptment Number', editable:true,type:dojox.grid.cells.Select, options:['730','731','732','733','734','735']},  {field: 'bonus', name: 'Bonus', editable: true ,width:"100px"}   ];  dojo.addOnLoad(function(){  var grid = new dojox.grid.DataGrid({  query: { emp_no: '*' },  // 查询字符串 id: 'grid2',            //DataGrid 的 id  autoWidth:true,        // 自动调整宽度 store: jsonStore,       // 使用 jsonStore 对象 structure: layout,       // 使用 layout 对象定义的结构 rowsPerPage: 20,       // 每页读取 20 条记录,保证 Web 浏览器的性能 headerMenu: gridMenu,  // 指定头菜单为 gridMenu  rowHeight: 35,   autoHeight:true }, 'gridNode');   grid.startup(); //grid 生效 });  </script>  </head>  <body class="tundra">  <div class="heading">Data Grid</div>  <div dojoType="dijit.Menu" jsid="gridMenu" id="gridMenu" style="display: none;"> <div dojoType="dojox.widget.PlaceholderMenuItem" label="GridColumns" ></div>  </div>  <div id="gridNode" style="height:850px;" />  </body>  </html>


0 0
原创粉丝点击