JavaScript的ExtJS框架中表格的编写教程

前端技术 2023/09/08 JavaScript

ExtJS中表格的特性简介
表格由类Ext.grid.GridPanel定义,继承自Ext.Panel,xtype为grid
表格的列信息由Ext.grid.ColumnModel定义
表格的数据存储器由Ext.data.Store定义,根据解析数据的不同,数据存储器可具体分为如下几种:

JsonStore,SimpleStore,GroupingStore…

一个表格的基本编写过程:

1、创建表格列模型

var cm = new Ext.grid.ColumnModel({
 {header: \'角色\', dataIndex: \'role\'},
 {header: \'等级\', dataIndex: \'grade\'},
 {header: \'创建日期\', dataIndex: \'createDate\', type: \'date\', renderer: Ext.util.Format.dateRenderer(\'Y年m月d日\')} //创建日期类型的数据
});

2、创建数据数组

var data = [
  [\'士兵\',\'7\',\'2011-07-2412:34:56\'],
  [\'将军\',\'10\',\'2011-07-2412:34:56\'],
];

3、创建一个数据存储对象store,包含两部分:proxy,获取数据的方式;reader,解析数据的方式

ArrayReader的mapping用来设置列的排列顺序

var store = new Ext.data.Store({
  proxy: new Ext.data.MemoryProxy(data),
  reader: new Ext.data.ArrayReader({}, [
    {name: \'role\', mapping: 1},
    {name: \'grade\', mapping: 0}
    {name: \'createDate\', mapping: 2, type:\'date\', dateFormat:\'Y-m-dH:i:s\'} //创建日期列和显示格式
  ])
});
store.load();

4、创建GridPanel,装配ColumnModel和store

var grid = new Ext.grid.GridPanel({
 renderTo: \'grid\',
 store: store,
 cm: cm
});

另外获取远程数据可以使用ScriptTagProxy,如下所示

var store = new Ext.data.Store({
  proxy: new Ext.data.ScriptTagProxy({
   url:\'http://...\'}),
  reader: new Ext.data.ArrayReader({}, [
    {name: \'role\', mapping: 1},
    {name: \'grade\', mapping: 0}
  ]),
  sortInfo: {field: \"role\", direction: \"ASC\"} //设置默认排序列,ASC/DESC
});


表格的常用属性功能

var grid = new Ext.grid.GridPanel({
 enableColumnMove: false, //禁止拖放列
 enableColumnResize: false, //禁止改变列的宽度
 stripeRows: true, //斑马线效果
 loadMask: true, //读取数据时的遮罩和提示功能
 renderTo: \'grid\',
 store: store
 cm: cm
});

var cm = new Ext.grid.ColumnModel({
 {header: \'角色\', dataIndex: \'role\', width:90, sortable: true}, //width设置列宽度,默认为100px,sortable设置排序功能
 {id:\'grade\', header: \'等级\', dataIndex: \'grade\', width:40}
});
var grid = new Ext.grid.GridPanel({
 renderTo: \'grid\',
 store: store,
 cm: cm
 viewConfig:{  //让每列自动填充满表格
 forceFit: true
 }
 autoExpandColumn: \'grade\' //自动延伸列,列的id在ColumnModel中定义
});

渲染表格,为表格设置特殊样式
只需要在cm里面增加一个renderer属性,添加一个自定义函数来渲染传进来(由EXT自动传递)的参数的样式即可,即在返回value之前拼装上相应的HTML和CSS或者JS响应事件。

function renderSex(value) {
  if (value == \'male\') {
    return \"<span style=\'color:blue;\'>男</span><img src=\'images/icon_male.png\' />\";
  } else {
    return \"<span style=\'color:red;\'>女</span><img src=\'images/icon_female.png\' />\";
  }
}

var cm = new Ext.grid.ColumnModel([
  {header:\'id\',dataIndex:\'id\'},
  {header:\'name\',dataIndex:\'name\'},
  {header:\'sex\',dataIndex:\'sex\',renderer:renderSex},
]);

var data = [
  [\'1\',\'Jason\',\'male\'],
  [\'2\',\'Kate\',\'female\']
];

var store = new Ext.data.Store({
  proxy: new Ext.data.MemoryProxy(data),
  reader: new Ext.data.ArrayReader({}, [
    {name: \'id\'},
    {name: \'name\'},
    {name: \'sex\'}
  ])
});
store.load();

var grid = new Ext.grid.GridPanel({
  autoHeight: true,
  renderTo: \'grid\',
  store: store,
  cm: cm
});

自动显示行号,只要在创建cm时创建一个RowNumberer就可以了

var cm = new Ext.grid.ColumnModel([
 new Ext.grid.RowNumberer(),  //显示行号
  {header:\'id\',dataIndex:\'id\'},
  {header:\'name\',dataIndex:\'name\'},
  {header:\'sex\',dataIndex:\'sex\',renderer:renderSex},
]);

删除列

store.remove(store.getAt(i));

刷新表格

grid.view.refresh();

为表格添加复选框
需要使用CheckboxSelectionModel
SelectionModel sm在使用时要放到cm和表格中

var sm = new Ext.grid.CheckboxSelectionModel();

var cm = new Ext.grid.ColumnModel([
  new Ext.grid.RowNumberer(),
  sm,
  {header:\'编号\',dataIndex:\'id\'},
  {header:\'名称\',dataIndex:\'name\'}
]);

var data = [
  [\'1\',\'name1\'],
  [\'2\',\'name2\']
];

var store = new Ext.data.Store({
  proxy: new Ext.data.MemoryProxy(data),
  reader: new Ext.data.ArrayReader({}, [
    {name: \'id\'},
    {name: \'name\'}
  ])

});
store.load();

var grid = new Ext.grid.GridPanel({
  autoHeight: true,
  renderTo: \'grid\',
  store: store,
  cm: cm,
  sm: sm
});

通过RowSelectionModel设置只选择一行:

var grid = new Ext.grid.GridPanel({
  autoHeight: true,
  renderTo: \'grid\',
  store: store,
  cm: cm,
  sm: new Ext.grid.RowSelectionModel({singleSelect:true})
});

使用选择模型获取数据

grid.on(\'click\', function() {
  var selections = grid.getSelectionModel().getSelections();
  for (var i = 0; i < selections.length; i++) {
    var record = selections[i];
    Ext.Msg.alert(record.get(\"id\"));
  }
});

表格视图
从MVC的思想来看表格控件:
* Ext.data.Store可看做模型
* Ext.grid.GridPanel可看做控制器
* Ext.grid.GridView可看做视图
* 一般GridView由GridPanell自动生成,如果想设置GridView的属性时,可以通过Ext.grid.GridPanel的getView()获得视图实例

Ext.get(\'button1\').on(\'click\', function() {
 grid.getView().scrollToTop();
  grid.getView().focusCell(0, 0);
  var cell = grid.getView().getCell(0, 0);
  cell.style.backgroundColor = \'red\';
});

使用GridPanel的viewConfig在创建表格时设置GridView的初始化参数

var grid = new Ext.grid.GridPanel({
  height: 100,
  width: 400,
  renderTo: \'grid\',
  store: new Ext.data.Store({
    autoLoad: true,
    proxy: new Ext.data.MemoryProxy(data),
    reader: new Ext.data.ArrayReader({}, meta)
  }),
  columns: meta,
  viewConfig: {
    columnsText: \'显示的列\', //设置下拉菜单提示文字
    scrollOffset: 30,  //设置右侧滚动条的预留宽度
    sortAscText: \'升序\',  //设置下拉菜单提示文字
    sortDescText: \'降序\',  //设置下拉菜单提示文字
    forceFit: true  //自动延展每列的长度
  }
});

为表格添加分页工具条
* 可以使用GridPanel的bbar属性,并创建Ext.PagingToolbar分页工具条对象
* 注意,如果配置了分页工具条,store.load()就必须在构造表格以后执行。

var grid = new Ext.grid.GridPanel({
  renderTo: \'grid\',
  autoHeight: true,
  store: store,
  cm: cm,
  bbar: new Ext.PagingToolbar({
    pageSize: 10,  //每页显示10条数据
    store: store,
    displayInfo: true,  //显示数据信息
    displayMsg: \'显示第 {0} 条到 {1} 条记录,一共 {2} 条\',
    emptyMsg: \"没有记录\"  //没有数据时显示的信息
  })
});
store.load();

从后台脚本获取分页数据

使用HttpProxy传递请求,获取服务器的JSON数据,交给JsonReader解析

var cm = new Ext.grid.ColumnModel([
  {header:\'编号\',dataIndex:\'id\'},
  {header:\'名称\',dataIndex:\'name\'}
]);
var store = new Ext.data.Store({
  proxy: new Ext.data.HttpProxy({url:\'page.jsp\'}),
  reader: new Ext.data.JsonReader({
    totalProperty: \'totalProperty\',
    root: \'root\'
  }, [
    {name: \'id\'},
    {name: \'name\'}
  ])
});
var grid = new Ext.grid.GridPanel({
  renderTo: \'grid\',
  autoHeight: true,  //数据传回来之前高度未知,所以要使用自适应高度
  store: store,
  cm: cm,
  bbar: new Ext.PagingToolbar({
    pageSize: 10,
    store: store,
    displayInfo: true,
    displayMsg: \'显示第 {0} 条到 {1} 条记录 / 共 {2} 条\',
    emptyMsg: \"没有记录\"
  })
});
store.load({params:{start:0,limit:10}});

如果想让分页工具条显示在表格的顶部,可以使用GridPanel的tbar属性设置添加工具条

让ExtJS在对返回的数据进行分页

* 需要在页面中引入examples/locale目录下的PagingMemoryProxy.js文件
* 再使用PagingMemoryProxy设置代理

var store = new Ext.data.Store({
  proxy: new Ext.data.PagingMemoryProxy(data),
  reader: new Ext.data.ArrayReader({}, [
    {name: \'id\'},
    {name: \'name\'},
    {name: \'descn\'}
  ])
});
//在创建GridPanel之后调用
store.load({params:{start:0,limit:3}});

可编辑表格控件EditorGrid的使用

制作一个简单的EditorGrid的步骤:

1、定义列ColumnModel,在里面添加editor属性

var cm = new Ext.grid.ColumnModel([{
  header: \'编号\',
  dataIndex: \'id\',
  editor: new Ext.grid.GridEditor(
    new Ext.form.TextField({
      allowBlank: false //不允许在TextField中输入空值
    })
  )
}, {
  header: \'名称\',
  dataIndex: \'name\',
  editor: new Ext.grid.GridEditor(
    new Ext.form.TextField({
      allowBlank: false
    })
  )
}]);

2、准备一个数组

var data = [
  [\'1\',\'Jason\'],
  [\'2\',\'Jay\']
];

3、创建Ext.data.Store,设置内存代理,设置ArrayReader解析数组

var store = new Ext.data.Store({
  proxy: new Ext.data.MemoryProxy(data),
  reader: new Ext.data.ArrayReader({}, [
    {name: \'id\'},
    {name: \'name\'}
  ])
});

4、加载数据,创建EditorGridPanel

store.load();
var grid = new Ext.grid.EditorGridPanel({
  autoHeight: true,
  renderTo: \'grid\',
  store: store,
  cm: cm
});

为可编辑表格添加和删除数据

1、使用Record的create方法创建一个记录集MyRecord,MyRecord相当于一个类

var MyRecord = Ext.data.Record.create([
  {name: \'id\', type: \'string\'},
  {name: \'name\', type: \'string\'}
]);
store.load();

2、创建EditorGridPanel面板,在属性tbar中创建Ext.Toolbar

var grid = new Ext.grid.EditorGridPanel({
  autoHeight: true,
  renderTo: \'grid\',
  store: store,
  cm: cm,
  tbar: new Ext.Toolbar([\'-\', { //-表示菜单分隔符
    text: \'添加一行\',
    handler: function(){
      var p = new MyRecord({
        id:\'\',
        name:\'\'
      });
      grid.stopEditing(); //关闭表格的编辑状态
      store.insert(0, p); //创建的Record插入store的第一行
      grid.startEditing(0, 0); //激活第一行第一列的编辑状态
    }
  }, \'-\', {
    text: \'删除一行\',
    handler: function(){
      Ext.Msg.confirm(\'信息\', \'确定要删除?\', function(btn){
        if (btn == \'yes\') {
          var sm = grid.getSelectionModel(); //获取表格的选择模型
          var cell = sm.getSelectedCell();  //获取选中的单元格
          var record = store.getAt(cell[0]); //通过行号得到store这一行对应的Record
          store.remove(record);  //移除数据
        }
      });
    }
  }, \'-\'])
});

为可编辑表格保存修改的结果

在上面例子的基础之上,添加一个保存按钮

text: \'保存\',
handler: function(){
  var m = store.modified.slice(0); //获得store中修改过得数据
  for (var i = 0; i < m.length; i++) { //验证表格信息是否正确,是否包含空格
    var record = m[i];
    var fields = record.fields.keys;

    for (var j = 0; j < fields.length; j++) {
      var name = fields[j];
      var value = record.data[name];

      var colIndex = cm.findColumnIndex(name);
      var rowIndex = store.indexOfId(record.id);
      var editor = cm.getCellEditor(colIndex).field;

      if (!editor.validateValue(value)) {
        Ext.Msg.alert(\'提示\', \'请检查输入的数据是否正确!\', function(){
          grid.startEditing(rowIndex, colIndex);
        });
        return;
      }
    }
  }
  var jsonArray = [];
  Ext.each(m, function(item) {
    jsonArray.push(item.data); //把修改过得数据放到jsonArray中
  });

  Ext.lib.Ajax.request(  //使用Ajax请求提交给后台
    \'POST\',
    \'save_data.jsp\',
    {success: function(response){ //返回成功
      Ext.Msg.alert(\'信息\', response.responseText, function(){
        store.reload();
      });
    },failure: function(){  //返回失败
      Ext.Msg.alert(\"错误\", \"服务器保存数据出错!\");
    }},
    \'data=\' + encodeURIComponent(Ext.encode(jsonArray))
  );
}

另外store可以设置属性pruneModifiedRecords: true。这样,每次remove或load操作时store会自动清除modified标记,可以避免出现下次提交时还会把上次那些modified信息都带上的现象。


限制表格输入的数据类型

NumberField

{
  header:\'ID\',
  dataIndex:\'id\',
  editor:new Ext.grid.GridEditor(new Ext.form.NumberField({ //NumberField限制只能输入数字
    allowBlank: false,
    allowNegative: false, //不能输入减号
    maxValue: 10
  }))
}

ComboBox

var comboData = [
  [\'0\',\'Java\'],
  [\'1\',\'Android\']
];
{
  header:\'ComboBox\',
  dataIndex:\'combo\',
  editor:new Ext.grid.GridEditor(new Ext.form.ComboBox({
    store: new Ext.data.SimpleStore({
      fields:[\'value\',\'text\'],
      data: comboData
    }),
    emptyText: \'请选择\',
    mode: \'local\',
    triggerAction: \'all\',
    valueField: \'value\',
    displayField: \'text\',
    readOnly:true
  })),
  renderer: function(value){
    return comboData[value][1];
  }
}

DateField

{
  header:\'Date\',
  dataIndex:\'date\',
  editor:new Ext.grid.GridEditor(new Ext.form.DateField({
    format: \'Y-m-d\',
    minValue: \'2011-07-24\',
    disabledDays: [0, 6],
    disabledDaysText: \'选择周一到周六之间的日期\'
  })),
  renderer: function(value) {
    return value.format(\"Y-m-d\");
  }
}

属性表格控件PropertyGrid的使用
是在EditorGrid的基础上开发的更智能的高级表格组件

var grid = new Ext.grid.PropertyGrid({
  title: \'属性表格控件PropertyGrid\',
  autoHeight: true,
  width: 400,
  renderTo: \'grid\',
  viewConfig: {
    forceFit: true
  },
  source: {
    \"String\": \"String\",
    \"Date\": new Date(Date.parse(\'07/24/2011\')),
    \"boolean\": false,
    \"float\": .01
  }
});

禁用PropertyGrid编辑功能的方法

grid.on(\'beforeedit\', function(e){
 e.cancel = true;
 return false;
});

根据表格的name获取value

grid.store.getById(\'Jason\').get(value);


ExtJS中实现嵌套表格
先看效果:

代码如下:

<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html>
<head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
<title>test</title>
<script type=\"text/javascript\">
</script>
<link rel=\"stylesheet\" type=\"text/css\" href=\"Lib/ExtJs/2_2/resources/css/ext-all.css\" />
<script type=\"text/javascript\" src=\"Lib/ExtJs/2_2/adapter/ext/ext-base.js\"></script>
<script type=\"text/javascript\" src=\"Lib/ExtJs/2_2/ext-all-debug.js\"></script>
<script type=\"text/javascript\" src=\"Lib/ExtJs/2_2/source/locale/ext-lang-zh_CN.js\"></script>
<script type=\"text/javascript\" src=\"Lib/ExtJs/plus/RowExpander.js\"></script>
<script type=\"text/javascript\">
Ext.onReady(function(){
var testData=[
  [\"lugreen\",\"男\",26,[[\"数学\",100],[\"语文\",150]]]
  ,[\"lisi\",\"男\",25,[[\"数学\",100],[\"语文\",150]]]
  ,[\"zhangsan\",\"男\",27,[[\"数学\",120],[\"语文\",158]]]  
];
//
storeTest= new Ext.data.SimpleStore({
  fields: [\"name\",\"sex\",\"age\",\"grade\"]
  ,data: testData
});
var expander = new Ext.grid.RowExpander({
    tpl : new Ext.XTemplate(
    \'<div class=\"detailData\">\',
    \'\',
    \'</div>\'
    )
    });
expander.on(\"expand\",function(expander,r,body,rowIndex){
 //查找 grid 
 window.testEle=body;
 //alert(body.id);
 if (Ext.DomQuery.select(\"div.x-panel-bwrap\",body).length==0){
   //alert(\"a\");
   var data=r.json[3];
   var store=new Ext.data.SimpleStore({
      fields: [\"class\",\"degrade\"]
      ,data:data
     });
   var cm = new Ext.grid.ColumnModel([
   {header: \"科目\",dataIndex: \'class\',width: 130,hideable:false,sortable:false,resizable:true}
   ,{header: \"成绩\",dataIndex: \'degrade\',width: 130,hideable:false,sortable:false,resizable:true}
   ]);
   Ext.DomQuery.select(\"div.detailData\")[0];
 var grid = new Ext.grid.GridPanel(
 {
  store:store,
  cm:cm,
  renderTo:Ext.DomQuery.select(\"div.detailData\",body)[0],
  autoWidth:true,
  autoHeight:true
  }
 );
 
 }
});
//var sm=new Ext.grid.CheckboxSelectionModel({singleSelect:true});
  var cm = new Ext.grid.ColumnModel([
  expander
  ,{header: \"姓名\",dataIndex: \'name\',width: 50,hideable:false,sortable:false}
  ,{header: \"性别\",dataIndex: \'sex\',width: 130,hideable:false,sortable:false,resizable:true}
  ,{header: \"年龄\",dataIndex: \'age\',width: 130,hideable:false,sortable:false,resizable:true}
  ]);
 var grid = new Ext.grid.GridPanel(
 {
  id:\'testgrid\',
  store:storeTest,
  cm:cm,
  renderTo:\"grid1\",
  width:780,
  autoHeight:false,
  height:300,
  listeners:{},
   plugins:[expander]
  }
  );
});
</script>
<style type=\"text/css\">
#div2 h2 {
  font-weight:200;
  font-size:12px;
}
.c1 h2 {
  font-weight:200;
}
</style>
</head>
<body>
<div id=\"grid1\">
 
</div>
<div id=\"grid2\">
 
</div>
</body>
</html>

其中使用到的\"RowExpander.js\"为extjs官方示例中自带的。

实现这个嵌套表格要注意两点技巧:
1.提供给外层表格的dataStore的数据源以嵌套数组的形式表示细节区的数据,如下面的黑体所示。

var testData=[
  [\"lugreen\",\"男\",26,[[\"数学\",100],[\"语文\",150]]]
  ,[\"lisi\",\"男\",25,[[\"数学\",100],[\"语文\",150]]]
  ,[\"zhangsan\",\"男\",27,[[\"数学\",120],[\"语文\",158]]]  
];

使用数组集中record对象的json属性来获取以细节区数据

var data=r.json[3];

2.在rowExpander的 expand事件中添加嵌套表格.

本文地址:https://www.stayed.cn/item/22191

转载请注明出处。

本站部分内容来源于网络,如侵犯到您的权益,请 联系我

我的博客

人生若只如初见,何事秋风悲画扇。