前言
在Ext js 中, 定义一个Grid 很方便,主要需要的是
1. 定义columns
2. 定义一个store 
3. 定义grid
var store1 = Ext.create('Ext.data.TreeStore', {
  fields: ['task1','task2','task3'],
    root:{
          "text": ".",
          "children": [{'task1':'11','task2':'22','task3':'33'}]
    }
});
  var treeGrid1 = Ext.create('Ext.tree.Panel',{
  header: 'Test Grid',
  renderTo: Ext.getBody(),
  collapsible: true,
  rootVisible: false,
  autoScroll: true,
  height: 600,
  store: store1,
  columns: [{"text":"Task 1","dataIndex":"task1"},
            {"text":"Task 2","dataIndex":"task2"},
            {"text":"Task 3","dataIndex":"task3"}]      
});以上是一个最简单的例子。
如何动态添加列
要动态添加一列, 也很简单
使用 Grid 的 reconfigure 方法就可以了。
var cols1 = [{"text":"Task 1","dataIndex":"task1"},
            {"text":"Task 2","dataIndex":"task2"},
            {"text":"Task 3","dataIndex":"task3"}
          ];
var store1 = Ext.create('Ext.data.TreeStore', {
  fields: ['task1','task2','task3'],
    root:{
          "text": ".",
          "children": [{'task1':'11','task2':'22','task3':'33'}]
    }
});
  var treeGrid1 = Ext.create('Ext.tree.Panel',{
  header: 'Test Grid',
  renderTo: Ext.getBody(),
  collapsible: true,
  rootVisible: false,
  autoScroll: true,
  height: 600,
  store: store1,
  columns: cols1      
});
  //dynamic add col
  cols1.push({"text":"Task 4","dataIndex":"task4"});
  treeGrid1.reconfigure(store1,cols1);也很简单。
双击编辑某行
配置行编辑的plugin 为Ext.grid.plugin.RowEditing, 设置某列编辑的editor
var cols1 = [{"text":"Task 1","dataIndex":"task1"},
            {"text":"Task 2","dataIndex":"task2",editor:{xtype:"textfield"}},
            {"text":"Task 3","dataIndex":"task3"}
          ];
var store1 = Ext.create('Ext.data.TreeStore', {
  fields: ['task1','task2','task3'],
    root:{
          "text": ".",
          "children": [{'task1':'11','task2':'22','task3':'33'}]
    }
});
  var treeGrid1 = Ext.create('Ext.tree.Panel',{
  header: 'Test Grid',
  renderTo: Ext.getBody(),
  collapsible: true,
  rootVisible: false,
  autoScroll: true,
  height: 600,
  store: store1,
  columns: cols1,
  plugins:[Ext.create('Ext.grid.plugin.RowEditing', {
	    clicksToMoveEditor: 2,
	    autoCancel: false
	})]
});
  //dynamic add col 
  cols1.push({"text":"Task 4","dataIndex":"task4"});
  treeGrid1.reconfigure(store1,cols1);同样很简单。
下面要进入重点了
带隐藏栏位的动态添加
现在有个需求是某个栏位默认是隐藏的。默认隐藏也很容易实现,直接设置hidden 为 true 就可以了。
比如说以上设置Task 2 这一列的hidden 为true 的话
var cols1 = [{"text":"Task 1","dataIndex":"task1"},
            {"text":"Task 2","dataIndex":"task2",editor:{xtype:"textfield"},"hidden":true},
            {"text":"Task 3","dataIndex":"task3"}
          ];
var store1 = Ext.create('Ext.data.TreeStore', {
  fields: ['task1','task2','task3'],
    root:{
          "text": ".",
          "children": [{'task1':'11','task2':'22','task3':'33'}]
    }
});
  var treeGrid1 = Ext.create('Ext.tree.Panel',{
  header: 'Test Grid',
  renderTo: Ext.getBody(),
  collapsible: true,
  rootVisible: false,
  autoScroll: true,
  height: 600,
  store: store1,
  columns: cols1,
  plugins:[Ext.create('Ext.grid.plugin.RowEditing', {
        clicksToMoveEditor: 2,
        autoCancel: false
    })]
});
  //dynamic add col 
  cols1.push({"text":"Task 4","dataIndex":"task4"});
  treeGrid1.reconfigure(store1,cols1);以上代码运行就会出现错误:
Uncaught TypeError: Object [object Object] has no method 'hasEditor'
如果使用debug 的js 的话, 会报在107028.
究其原因是:
1. Edit 的plugin 在初始化时会调用initFieldAccessors(columns)这个方法。 对每个列添加hasEditor 和 Editor 相关的一些方法和对象。
但是这里获取columns 的方法是 grid.getView().getGridColumns()
也就是说, hidden 的col 不会被找到
2. 而在执行reconfigure的时候又会用到hasEditor这个方法。导致找不到出错。
想到的解决思路有很多中:
1. 修改extjs 的 js 文件, 做非空判断。
这种方法需要修改 ext 本身的东西, 对于升级和维护的话都不是很好。
2. 还是从hasEditor这个方法入手。 对于hidden 类型的 col , 添加一个空的hasEditor方法。类似
{"text":"Task 2","dataIndex":"task2",editor:{xtype:"textfield"},"hidden":true:hasEditor:function(){}}错误是解决了。在view 的状态下是可以, 但是在edit 状态时, 编辑框的位置会错位,跑到最后面去。
3. 从plugin 入手。
以上方法不行,是否是因为不仅仅是要设置hasEditor,如果这样,模拟它本身的处理方式,调用initFieldAccessors(注意这个方法是 plugin 的)
plugin.initFieldAccessors(treeGrid.headerCt.getGridColumns());
var cols1 = [{"text":"Task 1","dataIndex":"task1"},
            {"text":"Task 2","dataIndex":"task2",editor:{xtype:"textfield"},"hidden":true},
            {"text":"Task 3","dataIndex":"task3"}
          ];
var store1 = Ext.create('Ext.data.TreeStore', {
  fields: ['task1','task2','task3'],
    root:{
          "text": ".",
          "children": [{'task1':'11','task2':'22','task3':'33'}]
    }
});
var plugin1 = Ext.create('Ext.grid.plugin.RowEditing', {
    clicksToMoveEditor: 2,
    autoCancel: false
});
  var treeGrid1 = Ext.create('Ext.tree.Panel',{
  header: 'Test Grid',
  renderTo: Ext.getBody(),
  collapsible: true,
    rootVisible: false,
    autoScroll: true,
    height: 600,
  store: store1,
  columns: cols1,
  plugins:plugin1
});
  plugin1.initFieldAccessors(treeGrid1.headerCt.getGridColumns()); 
  //dynamic add col 
  cols1.push({"text":"Task 4","dataIndex":"task4"});
  treeGrid1.reconfigure(store1,cols1);还是出现编辑框错位。
终极解决方法
看来此种状况无法使用hidden 来隐藏栏位了。
既然无法通过config 的方式隐藏, 在grid 创建出来之后使用 hide()方法来隐藏总可以吧。
配置的时候给一个 hiddencol 的名字(可以随便取)
{"text":"Task 2","dataIndex":"task2",hiddencol:true}写一个functionfunction hideGridCols(grid)
{
	if(grid!=null)
	{
		var gridCols = grid.headerCt.getGridColumns();
		if(gridCols!=null&&gridCols.length>0)
		{
			 for(var i=0;i<gridCols.length;i++)
			  {
				  var gridCol = gridCols[i];
				  var cfg = gridCol.initialConfig;
				  if(cfg.hiddencol!=null&&cfg.hiddencol===true)
				  {
					  gridCol.hide();
				  }		  
			  }
		}
	}		 
}在grid 创建完或是reconfig 的时候调用这个方法,问题解决。