前言
Ext js 创建一个多选下拉单的方式很简单, 使用Ext.form.ComboBox, 设置 multiSelect 为true 就可以了。
但是如果要在每个下拉之前加上一个checkbox, 如何实现呢?
ComboBox本身没有这样的配置,
有一个 “Ext.ux.form.MultiSelect” 这样一个扩展, 效果的话,是把选项全部显示出来。
没办法只能自己扩展一个这样的组件了。
界面实现
要实现这样的显示,可以使用ComboBox 的listConfig 这个配置。
可以配置listConfig的itemTpl来显示每个选项的显示效果,
itemTpl : Ext.create('Ext.XTemplate',
'<input type=checkbox>{value}'),
功能联动
显示效果出来了并没有介绍,
在选中某个选项时, 其前面的checkbox 应该是选中状态;
反选某个,其前面的checkbox 应该是非选中状态。
解决方式是在listConfig下配置 itemclick 的listeners
listeners:{
itemclick:function(view, record, item, index, e, eOpts ){
var isSelected = view.isSelected(item);
var checkboxs = item.getElementsByTagName("input");
if(checkboxs!=null)
{
var checkbox = checkboxs[0];
if(!isSelected)
{
checkbox.checked = true;
}else{
checkbox.checked = false;
}
}
}
}
动态store
以上方式在本地store 的状态下是可以的。
var states2 = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data : [
{"abbr":"AL", "name":"Alabama"},
{"abbr":"AK", "name":"Alaska"},
{"abbr":"AZ", "name":"Arizona"}
//...
]
});
但是通过ajax 方式取store 数据的状况就会出现一个问题。
proxy: {
type: 'ajax',
url: '/users.json',
reader: {
type: 'json',
root: 'users'
}
},
选中之后, 下一次点击下拉单的话, 之前选中的check box 会被取消选择。
原因是这种方式会更新 combobox 的下拉选项(combobox), 试图通过在refresh , render 事件中加入处理, 发现不行。
最终追踪代码,可以通过覆盖onItemSelect的方法实现。
完整代码
Ext.define('Ext.ux.MultiComboBox', {
extend: 'Ext.form.ComboBox',
alias: 'widget.multicombobox',
xtype: 'multicombobox',
initComponent: function(){
this.multiSelect = true;
this.listConfig = {
itemTpl : Ext.create('Ext.XTemplate',
'<input type=checkbox>{value}'),
onItemSelect: function(record) {
var node = this.getNode(record);
if (node) {
Ext.fly(node).addCls(this.selectedItemCls); var checkboxs = node.getElementsByTagName("input");
if(checkboxs!=null)
{
var checkbox = checkboxs[0];
checkbox.checked = true;
}
}
},
listeners:{
itemclick:function(view, record, item, index, e, eOpts ){
var isSelected = view.isSelected(item);
var checkboxs = item.getElementsByTagName("input");
if(checkboxs!=null)
{
var checkbox = checkboxs[0];
if(!isSelected)
{
checkbox.checked = true;
}else{
checkbox.checked = false;
}
}
}
}
}
this.callParent();
}
});