How to:Grid动态列
Grid是支持动态列的,该点体现在Ext.grid.GridPanel.reconfigure()中,其主要流程就是重新绑定列模型和插入新的Store数据源,然后刷新Grid视图。这里顺便给出源码:
reconfigure()方法接收两个参数,一个是store,一个是ColumnModel。如果数据源没有变化则可以是原来的Store的
(一般都是重新调配)。由于Grid是受Store控制加载数据的,reconfigure()过后只会在Grid显示列,实际的数据还需要
Store.load()绑定数据;另外分页工具条亦要重新定义Store对象,即pagingBar.bind(store)。这三个步骤简单表述如下:
关于Grid的动态列一定要说说别人写过的同类型题材文章。相关链接在这儿
。Neeke兄写的动态列例子写得比我这里更强大,可支持前三列为固定列,后N列为动态列这样子的Grid,如此便在进行复杂查询的时候非常有了。动态列的配置(包括单元格控件)通过Ext.Ajax.Request()完成。若适用的朋友请参考一下Neeke兄的博客文章。
ComboBox N层联动(级联菜单)
无刷新多级关联菜单是经常使用的UI功能。尽管Ext为我们提供了一个“高级的下拉列表”组件Combox,但涉及N级联动的菜单,还是与一般的
HTML
DropDownList即<select>元素考量的时候须注意的问题无异,可作为封装上的参考所使用,比如起码要支持N层的控件自动生成、怎样读取数据等等。下面以全国省市县为例子,制作多级联动菜单。dsy.Items保存了三层的数据,其结构比较简单,访问的索引为
“x1_x2_x3”,如下:
以上的代码就是完整的数据。linkComboBox如何实现?代码如下:
stores: [dsy.Items["0"], dsy.Items["0_0"], dsy.Items["0_0_0"]]
,isHoz: false
// @cfg 是否异步加载数据
,isRemoteLoad: false
// @overried
,initComponent: function(){
this.comboBox = [];
var
tbody = ''
,h = '<table cellspacing="10" style="border-collapse:separate;" mce_style="border-collapse:separate;"><tr>{0}</tr></table>'
,v = '<table cellspacing="10" style="border-collapse:separate;" mce_style="border-collapse:separate;">{0}</table>'
,id;
for(var i = 0, j = this.stores.length; i < j; i++){
id = Ext.id();
tbody += (this.isHoz ? '<td id="{0}"></td>' : '<tr><td id="{0}"></td></tr>').format(id);
this.comboBox.push(id);
}
this.html = this.isHoz ? h.format(tbody) : v.format(tbody);
linkComboBox.superclass.initComponent.apply(this, arguments);
}
// @overried
,afterRender: function(){
linkComboBox.superclass.afterRender.apply(this, arguments);
var combo;
for(var i = 0, j = this.comboBox.length; i < j; i++){
combo = new Ext.form.ComboBox({
linkId : 'linkId_' + i
,store : this.stores[i]
,mode : 'local'
,forceSelection : true // 必须选择一项
,editable : false // 不允许输入
,emptyText : '请选择分类...' //默认值
,triggerAction : 'all'
,hiddenName : 'interviewsDetail.parent_category' //hiddenName才是提交到后台的input的name
,name : 'parent'
,renderTo : this.comboBox[i]
,width : 200
});
combo.on('beforeSelect', this.resetBehind, this);
combo.on('beforeSelect', this.loadNext, this);
this.comboBox[i] = combo;
}
}
// @private
,resetBehind : function(combo, record, index){
// 看看打后的Combox,剩下的值都要被清空,设置过的都不算。
for(var i = (this.comboBox.indexOf(combo) + 1), j = this.comboBox.length; i < j; i++){
this.comboBox[i].clearValue(); // 清空选中的记录
}
}
// @private
,loadNext: function(combo, record, index){
var currentComboLinkId = this.comboBox.indexOf(combo);
if( currentComboLinkId + 1 < this.comboBox.length){
var nextCombo = this.comboBox[currentComboLinkId + 1];
var nO = nextCombo.getStore();
var key='0';
for(var i = 0; i < currentComboLinkId + 1; i++){ // 获取前面已选的记录,组成列表
key += "_" + this.getUpSelected(i);
}
nO.loadData(dsy.Items[key], false); // false等于nO.removeAll();
}
}
// private
,getUpSelected : function(currentComboLinkId){
var c = this.comboBox[currentComboLinkId];
return c.view.getSelectedIndexes()[0];
}
// public
,getValueByLevel:function(level){
return this.comboBox[level].getValue();
}
});
透过beforeSelect事件我们登记了两个事件处理器:resetBehind、loadNext。其中loadNext()是实现联动数据加载的关键方法,主要是获取前面各级选中的索引号形成符合dsy.Items访问的key,便能得到下一级的数据是什么,交由Combo渲染。只要数据源的数据结构经过适当的转换,就可以形成多级菜单的UI显示出来。
用法如下:
如图,此linkComboBox只是最简单的一个案例,还有许多细节功能未能来得及考虑,例如是否需要正向、逆向的选择,例如是否预选默认值、默认值之外又是否加载全体数据,还有的是全体加载数据、或者是异步加载……等等。
本例子在ext 3.2/IE6/FF3中通过。