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 的狀態下是可以的。
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(); }});