在Extjs中构造N级联动下拉的麻烦不少,需定制下拉数据并设定响应事件。通过对Combo集合的封装,无需自己配置Combo,只需设定数据和关联层级,即可自动构造出一组支持正向和逆向过滤的联动下拉并获取其中某一个的实例。
如:
数据:

Ext.test =
{};

Ext.test.lcbdata = [
{
level: 1, //下拉层级,可以是数字或字符串
type: '11', //所有父类别累加+本级类别
text: 'text1',//显示文本
value: '11'//值

},
{
level: 1,
type: '12',
text: 'text2',
value: '12'

},
{
level: 2,
type: '111',
text: 'text3',
value: '111'

},
{
level: 3,
type: '1111',
text: 'text4',
value: '1111'
}];

使用:
var lcb = new Ext.custom.LinkComboBag(Ext.test.lcbdata, [1, 2, 3]); //第二个参数的数组顺序就是下拉的层级顺序
var lv1 = lcb.getComboByLevel(1); //level值是1的ComboBox
var lv2 = lcb.getComboByLevel(2);
var lv3 = lcb.getComboByLevel(3);
实现:

Ext.custom =
{};


/**//**
* 封装了联动下拉的数据和数据结构转换的Ext类
* 需要传入数据:
* 1 联动下拉数据
* 2 combo数组(要求定义level属性)或者level数组
*
* @author 杨一
* @date 2009-7-1
*/

Ext.custom.LinkComboBag = function(data, combos)
{
this.data = data || [];
// 按照各个联动的顺序传入下拉数组
this.combos = combos || [];
// 持有各个联动数据的引用

this.stores =
{};
// 构造关联部分
var thisObj = this;
// 初始化下拉

for (var i = 0; i < combos.length; i++)
{

if(combos[i] instanceof Object)
{

}else
{

combos[i] =
{
level: combos[i]
}
}
combos[i].id = Ext.id();
combos[i]["xtype"] = 'combo';
combos[i]["editable"] = false;
combos[i]["emptyText"] = '请选择';
combos[i]["displayField"] = 'text';
combos[i]["valueField"] = 'value';
combos[i]["triggerAction"] = 'all';
combos[i]["mode"] = 'local';
combos[i]["store"] = this.buildStore(combos[i].level);
// 回调函数

combos[i]["listeners"] =
{

'beforeselect' : function(combo, record, index)
{
// 找到当前的下拉索引号

for (var k = 0; k < combos.length; k++)
{
if (combos[k].level === combo.level)
break;
}
// 遍历所有当前下拉后的组件下拉

for (var j = k + 1; j < combos.length; j++)
{
// 清空这些下拉的数据集
Ext.getCmp(combos[j].id).clearValue();
}
// 如果存在下一个下拉
if (k + 1 < combos.length)
// 把下一个下拉重新设定数据集
thisObj.change(combos[k + 1].level, record.get('type'));
thisObj.reverseSelect(combo.level, record.get('type'));
}
}
}
};

/**//**
* 按照索引获取下拉
*
* @param index
* 下拉索引
* @return 组件下拉
*/

Ext.custom.LinkComboBag.prototype.getComboByIndex = function(index)
{
return this.combos[index];
}


/**//**
* 按照层级获取下拉
*
* @param level
* 下拉层级
* @return 组件下拉
*/

Ext.custom.LinkComboBag.prototype.getComboByLevel = function(level)
{

for(var i=0;i<this.combos.length;i++)
{
if(this.combos[i].level == level)
return this.combos[i];
}
return null;
}


/**//**
* 建立一个默认的store并持有其引用
*
* @param level
* combo所属的层次
* @return 建立的数据集store
*/

Ext.custom.LinkComboBag.prototype.buildStore = function(level)
{
if (!this.stores[level])

this.stores[level] = new Ext.data.SimpleStore(
{
fields : ["type", "text", "value"],

sortInfo :
{
field : "type",
direction : "ASC"
}
});
this.initData(level);
return this.stores[level];
};


/**//**
* 根据制定的层级初始化一个combo使用的数据集 也可以采用Store:Filter的形式实现
*
* @param level
* combo所属的层次
* @param type
* 选项类别
*/

Ext.custom.LinkComboBag.prototype.initData = function(level)
{
var reData = [];
var index = 0;

for (var i = 0; i < this.data.length; i++)
{
if (this.data[i].level == level)
reData[index++] = [this.data[i].type, this.data[i].text,
this.data[i].value];
}
this.stores[level].loadData(reData, false);
};


/**//**
* 根据制定的层级及父类别更新一个combo使用的数据集 也可以采用Store:Filter的形式实现
*
* @param level
* combo所属的层次
* @param type
* 选项类别
*/

Ext.custom.LinkComboBag.prototype.change = function(level, type)
{
var reData = [];
var index = 0;

for (var i = 0; i < this.data.length; i++)
{
if (this.data[i].level == level
&& this.data[i].type.substr(0, type.length) === type)
reData[index++] = [this.data[i].type, this.data[i].text,
this.data[i].value];
}
this.stores[level].loadData(reData, false);
};


/**//**
* 反向选择,改变值,不改变数据集
*
* @param level
* combo所属的层次
* @param type
* 选项类别
*/

Ext.custom.LinkComboBag.prototype.reverseSelect = function(level, type)
{
//找到当前组件索引号

for (var k = 0; k < this.combos.length; k++)
{
if (this.combos[k].level === level)
break;
}
//遍历所有前面的组件

for(var j=k-1;j>=0;j--)
{

for (var i = 0; i < this.data.length; i++)
{
if (this.data[i].level == this.combos[j].level

&& type.substr(0, type.length - 2*(k - j)) == this.data[i].type)
{
Ext.getCmp(this.combos[j].id).setValue(this.data[i].value);
}
}
}
};
@2008 杨一. 版权所有. 保留所有权利